question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[QUESTION] Raw bytes as query parameter

See original GitHub issue

I’m using FastAPI to send pickled objects (using dill) to a remote server, but am having trouble sending/receiving my pickled object as raw bytes.

I’m using a POST endpoint and requests for sending the data. The closest I’ve come to success is to specify the pickled object parameter as a query parameter of type bytes:

@endpoint.post("/{my_var}")
async def runtask(
    my_var: str,
    obj_param: bytes,
):
<unpickle obj_param>

For example, using numpy’s subtract function and pickling with dill, I get a byte string like:

b'\x80\x03cnumpy\nsubtract\nq\x00.'

My POST looks like this (using requests.post and f strings to post the byte string object for obj_oparam):

http://127.0.0.1:8000/LpMetric?obj_param=b'%5Cx80%5Cx03cnumpy%5Cnsubtract%5Cnq%5Cx00.'

When I successfully receive this object at my endpoint, unpickling fails, because the byte string now looks like this:

b"b'\\x80\\x03cnumpy\\nsubtract\\nq\\x00.'"

The issue seems to be that FastAPI is assuming my obj_param is a string, and is therefore converting it to bytes, giving me a byte string of a byte string. I know that FastAPI treats raw bytes as strings “under the hood”, so is this expected behaviour? Am I doing something wrong when sending my pickled object, or is there something else I should be doing on the receiving end?

Hope that’s clear. I’m new to APIs so would really appreciate any help you can give. Thanks for your patience and thanks for your help!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
tincumagiccommented, Jan 9, 2020

You should encode the raw bytes in base64 then send encoded data as any normal string parameter and decode it on server as base64

3reactions
dmontagucommented, Jan 9, 2020

There’s a few issues to be aware of here:

  1. Yes, this is expected behavior in the sense that you are actually sending "b'\\x80\\x03cnumpy\\nsubtract\\nq\\x00.'" to the server, so FastAPI will treat the received value as the result of converting that string into bytes, as you are seeing.

    If you want to receive the original bytes, you need to make the request to your server with the actual bytes in your query parameter (url-encoded), not the stringified version that you are currently sending. (I’m not 100% sure whether query parameters are allowed to have arbitrary (url-encoded) bytes, though.)

  2. In general, you probably don’t want to put arbitrary bytes in the query string; typically data like that would go in the body. This can be achieved when making a client request using requests by something like requests.post(endpoint, data=my_pickled_bytes).

  3. Accepting pickled objects in a server endpoint is one of the most common and most serious security risks you’ll typically encounter during API development – if a malicious party gets access to the endpoint, they can immediately and easily execute arbitrary code on your server. You should absolutely never(!) expose such an endpoint to the open internet, or even to any untrusted user (basically, never in any kind of production environment where you aren’t the sole user).

    If you know what you are doing then it might be okay, but considering you said you are new to APIs I figured it was worth calling this out explicitly just in case.

For what it’s worth, if what you are trying to submit is something related to a numpy array, you might be better off using the tobytes method to convert the array to bytes, and the frombuffer function to load the bytes into an array on the server (you may also want to transmit the dtype as a separate field). This data could be sent with the request as part of a json payload, or as form data, and would prevent any remote code execution risk.

Read more comments on GitHub >

github_iconTop Results From Across the Web

how to get raw bytes from querystring - Stack Overflow
I found solution, need to use UrlDecode (with encoding specified) on Request.Url.Query: var wind1250 = Encoding.
Read more >
Query parameter targeting - Optimize Resource Hub
Query parameter targeting explicitly targets values that occur in the query string of a URL. Query parameters are found between the question mark...
Read more >
rest:get-raw-query-params - Documentation - MarkLogic
This function extracts all of the query parameters and returns them in a map. This does not include the parameters that would be...
Read more >
Lexical structure and syntax | BigQuery - Google Cloud
A bytes literal can be interpreted as raw bytes if both the r and b prefixes are present. These prefixes can be combined...
Read more >
Quickstart — Requests 2.28.1 documentation
... data would be given as key/value pairs in the URL after a question mark, e.g. httpbin.org/get?key=val . Requests allows you to provide...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found