How to structure a raw body in x-www-form-urlencoded format

Hello,

Iā€™m trying to use the twitter media API to upload an image and iā€™m struggling to understand how Postman is encoding the variables when using the x-www-form-urlencoded body type.

If i create a variable ā€˜media=iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYIIā€™ I can generate a 200 response using the x-www-form-urlencoded body

When i put the same body in Raw with a forced x-www-form-urlencoded header I get a 401 Unauthorized (which i think is just a poor error message bubbling up giving my Auth headers arenā€™t changing.

I presumed this was to do with URLEncoding, so i encoded the value to the below. When i do this in the x-www-form-urlencoded tab i now get a 400 for unsupported media type, and I still get the 401 through the raw body.

Console
When i look into the console for x-www-form-urlencoded I can see the structure it is sending the body in.

However, when i replicate that in raw, i still get a 401 so its doing something different. despite the text being identical, it also looks different in the console, so iā€™m not sure what iā€™m doing differently here.

Top works, bottom doesnt

Does anyone know how to structure the raw body, so it will simulate the same behaviour I get when using the x-www-form-urlencoded tab?

Encoded
iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD%2BwSzIAAAABlBMVEX%2F%2F%2F%2B%2Fv7%2BjQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD%2FaNpbtEAAAAASUVORK5CYII
Request:
POST https://upload.twitter.com/1.1/media/upload.json?
Documentation:
POST media/upload | Docs | Twitter Developer Platform

any ideas? or does anyone have a working collection i can try?

Hi @scales23

It looks to me like this is being sent as JSON from the screenshots you shared. Judging with the use of the colon after media.

Also, when you say top works, bottom doesnt. o you mean the first Request Body in the below screenshot works? How is it different form the one in the bottom?

Thanks for the response @gbadebo-bello

It looks to me like this is being sent as JSON from the screenshots you shared. Judging with the use of the colon after media.

  • Should it not be sent as JSON? Do you have an example of how the data should be structured for x-www-form-urlencoded?
    These are the different permutations i can think of, but iā€™m not sure what is correct here.
    ā€œkeyā€:ā€œvalueā€
    ā€œkeyā€:value
    key:value
    key:ā€œvalueā€
    ā€œkeyā€=ā€œvalueā€
    ā€œkeyā€=value
    key=value
    key=ā€œvalueā€

Also, when you say top works, bottom doesnt. o you mean the first Request Body in the below screenshot works? How is it different form the one in the bottom?

  • With regards to the top and bottom screenshots. That was showing how the console looks for the two requests. I was trying to show that when I use the x-www-form-urlencoded body, the console formats the body slightly differently (and the request works), vs when i use the raw body, whilst the data is identical, the formatting is different. This might be a red herring but it was a difference i couldnā€™t explain.

Just looking at those requests again;

x-www-url-encoded body

Request Headers
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth *****
Cache-Control: no-cache
Postman-Token: 93a600c0-68e9-48fe-9d8d-faa34283043f
Host: upload.twitter.com
Content-Length: 141
Cookie: guest_id=v1%3A171399458995171879; lang=en

Request Body
media: ā€œiVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYIIā€

Raw Body

Request Headers
Content-Type: application/x-www-form-urlencoded
Authorization: OAuth ****
Cache-Control: no-cache
Postman-Token: 8c1d7593-a36f-40f1-b175-27322ad09102
Host: upload.twitter.com
Content-Length: 128
Cookie: guest_id=v1%3A171399458995171879; lang=en

Request Body
media: ā€œiVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYIIā€

The key difference being the content length. The string is 128, so why does the x-www-form-urlencoded body submit a string of 141.

If i manually set a Content-Length as anything higher than 128 on my raw body request, it hangs and never completes a transaction. If i set it 128 or lower it fails in the same way as previously

What is the difference in how that is calculated compare to the raw body with a Content-Type: x-www-form-urlencoded

Hi @scales23
Iā€™m not sure what the issue is, but Iā€™ll keep looking.

Since youā€™re using the x-www-form-urlencoded body type and that works, why do you want to use a raw with a forced x-www-form-urlencoded header?

Thank you for supporting. Appreciate it.

It started out as a simple test just to prove i understand how the headers work, and has now turned into a frustrating cycle where on the face of it it should work but it doesnā€™t. Basically I just want to solve the problem :slight_smile:

Iā€™ve made a bit of progress with this using Fiddler. The format of the body is as such;

keyvalue=urlencoded(string)

i.e. media_data=iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD%2BwSzIAAAABlBMVEX%2F%2F%2F%2B%2Fv7%2BjQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD%2FaNpbtEAAAAASUVORK5CYII

Iā€™ve also managed to get a raw body working with this format, but only when I use the authorisation header generated from the x-www-url-encoded search. When i use the one from the raw body it fails.

So my next question @gbadebo-bello is how does the oauth_signature in the Authorisation header get generated between raw / x-www-url-encoded?

Think iā€™ve cracked it.

Looks like parameters are included in the oauth_signature generation when using x-www-form-urlencoded, but they are not when using the raw body.

This document pointed me in the right direction. The key bit being the media_data parameter in the body has to be part of the signature generation too.

The encoded parameters i used for the signature are (note alphabetical order)

media_category=tweet_image&media_data=ā€˜MediaDataā€™&oauth_consumer_key=ā€˜Consumer Keyā€™&oauth_nonce=ā€˜Nonceā€™&oauth_signature_method=HMAC-SHA1&oauth_timestamp=ā€˜Timestampā€™&oauth_token=ā€˜Access Tokenā€™&oauth_version=1.0

In summary the key bits that were missing that i worked through with thisā€¦for anyone wanting to use the media upload endpoint;

  • Body needs to be structured keyvalue=encoded(pair)
  • Content-Type: application/x-www-form-urlencoded
  • Content-Length header needs to be sent and the encoded length
  • oauth_signature needs to be generated using both url and body parameters
1 Like

Hi @scales23. Good to see youā€™ve been able to resolve this.

Cheers!