Open pranavs18 opened 6 years ago
Hey @pranavs18, can you give me a workable code example that allows me to reproduce the problem you describe here? It would be helpful for me to figure what's going on there for you :)
router["/image"] = JSONResponse(handler: {environ -> Any in
let input = environ["swsgi.input"] as! SWSGIInput
DataReader.read(input) { data in
// get the image bytes from the request object
funcABC(data)
startResponse("200 OK", [])
sendBody(Data("".utf8))
sendBody(Data())
}
return ["Image processed":"1"]
}
I am trying to use curl -v -X POST -F 'file=@temp.jpg' http://localhost:8080/image
. This would do the multi-part form-data image upload. The issue with the above code snippet is that when we run the above curl command, the data in the closure is empty. I believe, since it's a multi part form-data upload on the server side, I would need to extract the file
field from the http request body object to get the bytes. How can I do this using embassy?
If I were to do this in swift in another http framework, I can perhaps do this like:
let content = request.formData?["file"]?.part.body
// get bytes
let d = Data(bytes: content)
@pranavs18 JSONResponse
will respond immediately after you return via return ["Image processed":"1"]
. Then it will close the HTTP connection. DataReader.read(input)
is an async operation, which means it will wait until new HTTP body data arrive. So when JSONResponse
handler returns, DataReader.read
won't get a chance to really read the data.
As if you want to read the complete HTTP body payload, you will need to wait until DataReader.read
called the callback then send the response to peer. For JSONResponse
, there's another async constructor you can use
Like this, you can modify your code with the sendJSON for finishing up the response
router["/image"] = JSONResponse(handler: { (environ, sendJSON) -> Any in
let input = environ["swsgi.input"] as! SWSGIInput
DataReader.read(input) { data in
// get the image bytes from the request object
funcABC(data)
sendJSON(["Image processed":"1"])
}
}
I did try this before and it gives me a compilation error at the handler:{ (
: Unable to infer closure type in the current context
. I am using swift 4.1
router["/image"] = JSONResponse(handler: { (environ, sendJSON) -> Any in
let input = environ["swsgi.input"] as! SWSGIInput
DataReader.read(input) { data in
funcABC(data)
sendJSON(["Image processed":"1"])
}
})
It works if I change Any
to void
and I do get the bytes of the image uploaded. But I wonder how do I extract the image content from there ?
This snippet compiles but the data passed in funcABC() expects an image but fails to find that. When I print data, it gives me the total bytes. How would I extract the file content from there ?
router["/image"] = JSONResponse(handler: { (environ, sendJSON) -> Void in
let input = environ["swsgi.input"] as! SWSGIInput
DataReader.read(input) { data in
funcABC(data)
sendJSON(["Image processed":"1"])
}
})
I actually figured out the problem.
When I used curl with --data-binary @temp.jpg
, that worked like a charm. All the bytes were correctly received and processed.
When I used curl with -F "file=@temp.jpg
, that fails. And it is probably because, the extra string file=
and the multipart form-data boundary bytes need to be extracted away I believe from the total bytes uploaded. In this case, the total bytes uploaded are much more than in the case of --data-binary
.
May be, you could add support for processing multi-part form-data as well.
@fangpenlin Are there any plans or a workaround for supporting multi-part form-data?
Is the ambassador authorizer now allowing multipart form data parameters to be passed through?
Can someone give an example of how to handle POST requests where we are uploading files/photos (multipart/form-data).
I tried to use
DataReader(input)
snippet but that always gives me an empty data back. Does environ need to have another key set ? Looking at python's uwsgi definitions, they advise to use cgi.FieldStorage.d = cgi.FieldStorage(environ=environ, fp=environ['wsgi.input'], keep_blank_values=True)
Could you provide an example of how do we handle this case ?
DataReader.read(input) { d in print(d) }
In this case, when using
curl -v -X POST -F 'file=@temp.jpg' http://localhost:8080/image
, thed
variable declared above is nil.