mirror of https://github.com/certusone/dc4bc.git
WIP: http server for client
This commit is contained in:
parent
06ef734c63
commit
b7da6b06b2
|
@ -95,18 +95,26 @@ func (c *Client) GetOperations() (map[string]*Operation, error) {
|
|||
return c.state.GetOperations()
|
||||
}
|
||||
|
||||
// GetOperationQRPath returns a path to the image with the QR generated
|
||||
// for the specified operation. It is supposed that the user will open
|
||||
// this file herself.
|
||||
func (c *Client) GetOperationQRPath(operationID string) (string, error) {
|
||||
func (c *Client) getOperationJSON(operationID string) ([]byte, error) {
|
||||
operation, err := c.state.GetOperationByID(operationID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get operation: %w", err)
|
||||
return nil, fmt.Errorf("failed to get operation: %w", err)
|
||||
}
|
||||
|
||||
operationJSON, err := json.Marshal(operation)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to marshal operation: %w", err)
|
||||
return nil, fmt.Errorf("failed to marshal operation: %w", err)
|
||||
}
|
||||
return operationJSON, nil
|
||||
}
|
||||
|
||||
// GetOperationQRPath returns a path to the image with the QR generated
|
||||
// for the specified operation. It is supposed that the user will open
|
||||
// this file herself.
|
||||
func (c *Client) GetOperationQRPath(operationID string) (string, error) {
|
||||
operationJSON, err := c.getOperationJSON(operationID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get operation in JSON: %w", err)
|
||||
}
|
||||
|
||||
operationQRPath := filepath.Join(QrCodesDir, operationID)
|
||||
|
@ -131,6 +139,10 @@ func (c *Client) ReadProcessedOperation() error {
|
|||
return fmt.Errorf("failed to unmarshal processed operation")
|
||||
}
|
||||
|
||||
return c.handleProcessedOperation(operation)
|
||||
}
|
||||
|
||||
func (c *Client) handleProcessedOperation(operation Operation) error {
|
||||
storedOperation, err := c.state.GetOperationByID(operation.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find matching operation: %w", err)
|
||||
|
|
|
@ -3,7 +3,9 @@ package client
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/depool/dc4bc/qr"
|
||||
"github.com/depool/dc4bc/storage"
|
||||
"image"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
@ -28,6 +30,9 @@ func (c *Client) StartHTTPServer(listenAddr string) error {
|
|||
http.HandleFunc("/getOperations", c.getOperationsHandler)
|
||||
http.HandleFunc("/getOperationQRPath", c.getOperationQRPathHandler)
|
||||
http.HandleFunc("/readProcessedOperationFromCamera", c.readProcessedOperationFromCameraHandler)
|
||||
|
||||
http.HandleFunc("/readProcessedOperation", c.readProcessedOperationFromBodyHandler)
|
||||
http.HandleFunc("/getOperationQR", c.getOperationQRToBodyHandler)
|
||||
return http.ListenAndServe(listenAddr, nil)
|
||||
}
|
||||
|
||||
|
@ -93,6 +98,30 @@ func (c *Client) getOperationQRPathHandler(w http.ResponseWriter, r *http.Reques
|
|||
successResponse(w, []byte(qrPath))
|
||||
}
|
||||
|
||||
func (c *Client) getOperationQRToBodyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
|
||||
return
|
||||
}
|
||||
operationID := r.URL.Query().Get("operationID")
|
||||
|
||||
operationJSON, err := c.getOperationJSON(operationID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to get operation in JSON: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
encodedData, err := qr.EncodeQR(operationJSON)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to encode operation: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "image/jpeg")
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(encodedData)))
|
||||
successResponse(w, encodedData)
|
||||
}
|
||||
|
||||
func (c *Client) readProcessedOperationFromCameraHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
|
||||
|
@ -101,9 +130,49 @@ func (c *Client) readProcessedOperationFromCameraHandler(w http.ResponseWriter,
|
|||
|
||||
if err := c.ReadProcessedOperation(); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError,
|
||||
fmt.Sprintf("failed to read processed operation from camera path: %v", err))
|
||||
fmt.Sprintf("failed to handle processed operation from camera path: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
successResponse(w, []byte("ok"))
|
||||
}
|
||||
|
||||
func (c *Client) readProcessedOperationFromBodyHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
errorResponse(w, http.StatusBadRequest, "Wrong HTTP method")
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.ParseMultipartForm(10 << 20); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to parse multipat form: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
file, _, err := r.FormFile("qr")
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to retrieve a file: %v", err))
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
img, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to decode an image: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
qrData, err := qr.ReadDataFromQR(img)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var operation Operation
|
||||
if err = json.Unmarshal(qrData, &operation); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError,
|
||||
fmt.Sprintf("failed to unmarshal processed operation: %v", err))
|
||||
return
|
||||
}
|
||||
if err := c.handleProcessedOperation(operation); err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, fmt.Sprintf("failed to handle an operation: %v", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
25
qr/qr.go
25
qr/qr.go
|
@ -67,18 +67,7 @@ loop:
|
|||
return nil, fmt.Errorf("failed to get image object: %w", err)
|
||||
}
|
||||
|
||||
bmp, err := gozxing.NewBinaryBitmapFromImage(imgObject)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get NewBinaryBitmapFromImage: %w", err)
|
||||
}
|
||||
|
||||
qrReader := qrcode.NewQRCodeReader()
|
||||
result, err := qrReader.Decode(bmp, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the QR-code contents: %w", err)
|
||||
}
|
||||
|
||||
return result.GetRawBytes(), err
|
||||
return ReadDataFromQR(imgObject)
|
||||
}
|
||||
|
||||
func (p *CameraProcessor) WriteQR(path string, data []byte) error {
|
||||
|
@ -90,12 +79,20 @@ func (p *CameraProcessor) WriteQR(path string, data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func ReadQRFromImg(img image.Image) (*gozxing.Result, error) {
|
||||
func ReadDataFromQR(img image.Image) ([]byte, error) {
|
||||
bmp, err := gozxing.NewBinaryBitmapFromImage(img)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get NewBinaryBitmapFromImage: %w", err)
|
||||
}
|
||||
|
||||
qrReader := qrcode.NewQRCodeReader()
|
||||
return qrReader.Decode(bmp, nil)
|
||||
result, err := qrReader.Decode(bmp, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the QR-code contents: %w", err)
|
||||
}
|
||||
return result.GetRawBytes(), nil
|
||||
}
|
||||
|
||||
func EncodeQR(data []byte) ([]byte, error) {
|
||||
return encoder.Encode(string(data), encoder.Medium, 512)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue