Closed tobeliketree closed 6 years ago
Second this - I also started being unable to send URL encoded '+' signs in GET requests.
Postman Version: 4.9.1 App (Chrome app or Mac app): Mac App OS details: MacOs Sierra (10.11.6) Is the Interceptor on and enabled in the app: no Did you encounter this recently, or has this bug always been there: Recently, after upgrade Expected behavior: Query params in GET request encoded as %2B are not modified incorrectly by Postman.
Example: GET /users/{{user}}/preference?phoneInQuestion=%2B19991114444
If I generate code to a curl request for instance, the url that is generated looks like: GET /users/{{user}}/preference?phoneInQuestion=%252B19991114444
It seems that Postman is url encoding the '%' and leaving everything else which is incorrect.
I think this might be related to: https://github.com/postmanlabs/postman-app-support/issues/2538 We are looking into this.
How do we downgrade for now @madebysid ? Really cant use postman at all with such a showstopper issue.
@rickmills Could you drop a mail at help@getpostman.com?
Possible duplicate of #2468, related to #2510, #2508
Same problem here. Our system generates authentication keys that users must send in each request. In several API that key is sent as a GET parameter. After updating to 4.9.x the problem began. When the key has a plus sign (+) the requests do not work. Is there a solution or workaround for that yet?
Same problem here. How do I downgrade or when can this get fixed? Its kind-of a big deal here as email addressed "tagged" with '+' (user.name+tag@example.com) are really popular on our service. There's not a test case for URL encoding in Postman?
I'm the original poster and would love an update. This has been really disruptive to my work and I see that I'm not alone here. The status is....?
@tobeliketree @robertkuhar @mhertogs @rickmills The issue has been fixed in our latest canary(4.9.4-canary.1) release, can you guys switch to that version an check the same? On additional note we are using the whatwg's url parser algorithm.
@tobeliketree @robertkuhar @mhertogs @rickmills Just a nudge to check whether you guys had chance to test it out in canary build. OSX: https://dl.pstmn.io/download/channel/canary/osx_64 Windows 32-bit: https://dl.pstmn.io/download/channel/canary/windows_32 Windows 64-bit: https://dl.pstmn.io/download/channel/canary/windows_64 Linux 32-bit: https://dl.pstmn.io/download/channel/canary/linux_32 Linux 64-bit: https://dl.pstmn.io/download/channel/canary/linux_64
Hi @SamvelRaja
Tested it out this morning and the Canary release does appear to fix the issue on macOS :)
Thanks for that 👍
@SamvelRaja I confirmed that the canary does indeed allow me to manually encode the '+' in the GET URLs and generates an HTTP request that works when I click "Send". That is to say setting a query param like email=robert.kuhar%2Bprime@climate.com
on the Postman URL (ex. http://example.com/user/details?email=robert.kuhar%2Bprime@climate.com) works like a champ.
It still strikes me as odd that the "cURL" from both the failed Postman URL (http://example.com/user/details?email=robert.kuhar+plus@climate.com) and the now respected "pre-http-encoded" Postman URL (http://example.com/user/details?email=robert.kuhar%2Bplus@climate.com) generate the exact same cURL and that cURL is correct.
In other words, a Postman URL of http://example.com/user/details?email=robert.kuhar+plus@climate.com
will fail on Send but the cURL generated from it will succeed
curl -X GET -H "Accept: application/json" -H "x-http-request-id: GET_user_by_email" -H "x-http-caller-id: tcc-rkuhar.local" -H "Cache-Control: no-cache" -H "Postman-Token: eaaa3c49-2da9-7d89-ee5a-f92391399a23" "http://example.com/user/details?email=robert.kuhar%2Bplus@climate.com"
Maybe I shouldn't "look a gift horse in the mouth". Postman can now do common email aliases as query parameters and that alone is progress. Wahoo!
I tested this on OSX
@robertkuhar Thanks for testing and providing the information, the mismatch between the cURL and the postmanURL is intentional, I will look further into this and will update the thread accordingly.
@SamvelRaja The canary link you gave does solve my encoding problem when using Postman directly (I am using OSX). However, when I generate cURL requests, it seems you are URL encoding in the actual URL path as well which is messing up our REST resource paths.
Example: /v1/phones/+19998887777 becomes /v1/phones/%2B19998887777
According to RFC 1738: "Thus, only alphanumerics, the special characters "$-_.+!*'(),", and reserved characters used for their reserved purposes may be used unencoded within a URL."
I still think this fix is good enough to unblock a lot of people so I would still recommend moving forward with it, but there should probably some future consideration about how to treat special characters in a URL path without just encoding them all because there are valid URLs that leave these unencoded.
@mhertogs Thanks for your valuable feedback on the canary app. Right now i came to the fact that + needs to be encoded in the path of the URL in cURL code generator as %2B and it needs to be either encoded as %20 or left as it is as + in the query params. I will keep the issue open for further discussions and ideas from the users and community.
I'm having some problems parsing dates in the ISO8601 format. My request looks like this:
{{url}}?departure=2017-03-01T12:05:00+01:00
When I fire this off in the postman app, debugging my app shows the incoming string as "2017-03-01T12:05:00 01:00". This is not what I want - I want to keep the +
sign.
But if I generate a cURL request I get this:
curl -X GET "http://myUrl?departure=2017-03-01T12:05:00%2B01:00"
and that works as expected. Debugging shows the incoming string as "2017-03-01T12:05:00+01:00".
Trying to change my request to look like this instead:
{{url}}?departure=2017-03-01T12:05:00%2B01:00
didn't help. I get the same resulting string in my application: "2017-03-01T12:05:00 01:00".
@stianlagstad Can you provide the version of the app you face this? I am testing in the current 4.10.2 version of the Mac app and it sends the %2B as expected.
I'm getting the same as you for the url
, but look at args.departure
above. That contains a space, which is not what I want. I want args.departure
to be "2017-03-01T12:05:00+01:00", not "2017-03-01T12:05:00 01:00".
Again: The generated cURL request works:
curl -X GET "http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00"
Also:
You are up to date! Postman v4.10.2 is the latest version.
@stianlagstad My bad, Attached a wrong screen shot, yes i am getting the '+' in the args.departure, if i send the departure=2017-03-01T12:05:00%2B01:00
as query param.
Then there's a difference between the behaviour in your app and in mine. This is what I see:
Can I fix this somehow?
I'm using Postman v4.10.2 on Ubuntu 16.04.
@stianlagstad This seems really odd :( I would like you to open the app in debug mode to find the underlying request sent.
for that close the postman app if already opened, then you need to run the following command in your terminal
NODE_DEBUG=request /PATH_TO_THE_APP/Postman.app/Contents/MacOS/Postman
where PATH_TO_THE_APP would be either to your /Downloads/
folder or /Applications/
folder.
This will open the postman app in debug mode. Once it is opened, send the same request.
You can find the request data sent to your server something like below.
Kindly provide the screen shot of that to help us to debug much further.
Like this?
➜ Postman NODE_DEBUG=request ./Postman
REQUEST { headers:
{ 'User-Agent': 'PostmanRuntime/3.0.11-hotfix.2',
Accept: '*/*',
Host: 'echo.getpostman.com' },
url: 'http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00',
method: 'GET',
jar:
RequestJar {
_jar:
CookieJar {
rejectPublicSuffixes: false,
enableLooseMode: true,
store:
{ .. } } },
gzip: true,
useQuerystring: true,
strictSSL: true,
followRedirect: true,
followAllRedirects: true,
encoding: null,
agentOptions: { keepAlive: true },
request:
PostmanRequest {
description: PostmanPropertyDescription { content: undefined, type: 'text/plain' },
url:
PostmanUrl {
auth: undefined,
protocol: undefined,
port: undefined,
path: [Object],
hash: undefined,
host: [Object],
query: [Object],
variables: [Object] },
method: 'GET',
headers:
PostmanPropertyList {
members: [],
reference: {},
Type: [Object],
_postman_listIndexKey: 'key',
_postman_listIndexCaseInsensitive: true },
body: PostmanRequestBody {},
auth: PostmanRequestAuth {},
_: { _postman_proxy: undefined } },
certificateManager:
callIntoRenderer {
length: 0,
models: [],
_byId: {},
getCertificateContents: [Function: callIntoRenderer],
model: [Function: callIntoRenderer],
initialize: [Function: callIntoRenderer],
loadCertificates: [Function: callIntoRenderer],
saveCertificates: [Function: callIntoRenderer],
findCertificateByDomain: [Function: callIntoRenderer],
addCertificate: [Function: callIntoRenderer],
updateCertificate: [Function: callIntoRenderer],
removeCertificate: [Function: callIntoRenderer],
constructor: [Function: callIntoRenderer],
on: [Function: callIntoRenderer],
listenTo: [Function: callIntoRenderer],
off: [Function: callIntoRenderer],
stopListening: [Function: callIntoRenderer],
once: [Function: callIntoRenderer],
listenToOnce: [Function: callIntoRenderer],
trigger: [Function: callIntoRenderer],
bind: [Function: callIntoRenderer],
unbind: [Function: callIntoRenderer],
toJSON: [Function: callIntoRenderer],
sync: [Function: callIntoRenderer],
add: [Function: callIntoRenderer],
remove: [Function: callIntoRenderer],
set: [Function: callIntoRenderer],
reset: [Function: callIntoRenderer],
push: [Function: callIntoRenderer],
pop: [Function: callIntoRenderer],
unshift: [Function: callIntoRenderer],
shift: [Function: callIntoRenderer],
slice: [Function: callIntoRenderer],
get: [Function: callIntoRenderer],
has: [Function: callIntoRenderer],
at: [Function: callIntoRenderer],
where: [Function: callIntoRenderer],
findWhere: [Function: callIntoRenderer],
sort: [Function: callIntoRenderer],
pluck: [Function: callIntoRenderer],
fetch: [Function: callIntoRenderer],
create: [Function: callIntoRenderer],
parse: [Function: callIntoRenderer],
clone: [Function: callIntoRenderer],
modelId: [Function: callIntoRenderer],
_reset: [Function: callIntoRenderer],
_prepareModel: [Function: callIntoRenderer],
_removeModels: [Function: callIntoRenderer],
_isModel: [Function: callIntoRenderer],
_addReference: [Function: callIntoRenderer],
_removeReference: [Function: callIntoRenderer],
_onModelEvent: [Function: callIntoRenderer],
forEach: [Function: callIntoRenderer],
each: [Function: callIntoRenderer],
map: [Function: callIntoRenderer],
collect: [Function: callIntoRenderer],
reduce: [Function: callIntoRenderer],
foldl: [Function: callIntoRenderer],
inject: [Function: callIntoRenderer],
reduceRight: [Function: callIntoRenderer],
foldr: [Function: callIntoRenderer],
find: [Function: callIntoRenderer],
detect: [Function: callIntoRenderer],
filter: [Function: callIntoRenderer],
select: [Function: callIntoRenderer],
reject: [Function: callIntoRenderer],
every: [Function: callIntoRenderer],
all: [Function: callIntoRenderer],
some: [Function: callIntoRenderer],
any: [Function: callIntoRenderer],
include: [Function: callIntoRenderer],
includes: [Function: callIntoRenderer],
contains: [Function: callIntoRenderer],
invoke: [Function: callIntoRenderer],
max: [Function: callIntoRenderer],
min: [Function: callIntoRenderer],
toArray: [Function: callIntoRenderer],
size: [Function: callIntoRenderer],
first: [Function: callIntoRenderer],
head: [Function: callIntoRenderer],
take: [Function: callIntoRenderer],
initial: [Function: callIntoRenderer],
rest: [Function: callIntoRenderer],
tail: [Function: callIntoRenderer],
drop: [Function: callIntoRenderer],
last: [Function: callIntoRenderer],
without: [Function: callIntoRenderer],
difference: [Function: callIntoRenderer],
indexOf: [Function: callIntoRenderer],
shuffle: [Function: callIntoRenderer],
lastIndexOf: [Function: callIntoRenderer],
isEmpty: [Function: callIntoRenderer],
chain: [Function: callIntoRenderer],
sample: [Function: callIntoRenderer],
partition: [Function: callIntoRenderer],
groupBy: [Function: callIntoRenderer],
countBy: [Function: callIntoRenderer],
sortBy: [Function: callIntoRenderer],
indexBy: [Function: callIntoRenderer],
findIndex: [Function: callIntoRenderer],
findLastIndex: [Function: callIntoRenderer] },
proxyManager: { getProxyConfiguration: [Function: callIntoRenderer] },
callback: [Function] }
REQUEST make request http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00
REQUEST onRequestResponse http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00 200 { server: 'nginx/1.10.1',
date: 'Wed, 01 Mar 2017 09:05:31 GMT',
'content-type': 'application/json; charset=utf-8',
'transfer-encoding': 'chunked',
'access-control-allow-origin': '',
'access-control-allow-credentials': '',
'access-control-allow-methods': '',
'access-control-allow-headers': '',
'access-control-expose-headers': '',
etag: 'W/"1af-k/bY8OyRv+bjQuNBJouEVA"',
vary: 'Accept-Encoding',
connection: 'Keep-Alive',
'content-encoding': 'gzip',
age: '0' }
REQUEST reading response's body
REQUEST finish init function http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00
REQUEST response end http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00 200 { server: 'nginx/1.10.1',
date: 'Wed, 01 Mar 2017 09:05:31 GMT',
'content-type': 'application/json; charset=utf-8',
'transfer-encoding': 'chunked',
'access-control-allow-origin': '',
'access-control-allow-credentials': '',
'access-control-allow-methods': '',
'access-control-allow-headers': '',
'access-control-expose-headers': '',
etag: 'W/"1af-k/bY8OyRv+bjQuNBJouEVA"',
vary: 'Accept-Encoding',
connection: 'Keep-Alive',
'content-encoding': 'gzip',
age: '0' }
REQUEST end event http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00
REQUEST has body http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00 431
REQUEST emitting complete http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00
I removed what was in jar.RequestJar._jar.CookieJar.store
, because that looked like my own unrelated data.
What I see in postman is the same as before:
It must have to do with how the Postman app sends the request, because if I do the cURL-call it works as expected:
➜ Postman curl -X GET "http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00"
{"args":{"departure":"2017-03-01T12:05:00+01:00"},"headers":{"host":"echo.getpostman.com","user-agent":"curl/7.47.0","accept":"*/*","cache-control":"max-stale=0","x-bluecoat-via":"cc52d5680b6e1cd0"},"url":"http://echo.getpostman.com/get?departure=2017-03-01T12:05:00%2B01:00"}%
The response there is what I want.
@stianlagstad The log you shared ensures that postman actually sending the %2B as it is to the server 😢 I am still wondering why it is showing differently for you in the response UI. can you make sure that app sends the request in the format as you expected even to your server as well ? through your app server logs. And cURL, yeah app should behave in the same way.
I'm not sure if that is right. There's clearly a difference between what reaches my server when I send the request from within the postman app (there's a space in the date), versus if I generate cURL and send the request through the command line (%2B
instead of a space in the date). I'd stretch it as far as to wonder whether the logs that you asked me to check are correct? If the same error is occuring there, then the logs might look normal.
I'm not sure how to investigate this further :(
This IS a bug and it is still present in most recent version of Postman (there is no way to view version info from Postman interface, so sorry for not providing exact version).
Get parameter expired
with value 2018-04-15 22:29:59 +0300
results in expired=2018-04-15 22:29:59 0300
. Because plus sign isn't escaped and is parsed as a space by server.
I second this, we also have problems with it
We are following a master thread #4555 to track all issues related to Url encoding. Please follow that issue for updates.
The "+" symbol should is still not encoded in URL queries as "%2B" in Postman ver. Version 7.11.0 on win32 6.1.7601 / x64
2023, not encoded.
2023 Oct, still happening
22 March 2024, still not working!
I have an authentication request that uses an email address with a plus sign that was working previously until my app updated to v 4.9.0. Now my get request fails on the email address.
The email address I'm using looks like email+alias@email.com and I am using a {{email}} variable to insert this in the url. I am doing the same as well as the password and API key.
/authenticate?api_key={{api_key}}&email={{email}}&password={{password}}
This is the code that is being sent to the server via postman which is now failing.
GET /psapi/v3/mem/authenticate?api_key=DuMMyApiKeY&email=email+alias@email.com&password=abc123 Host: www.photoshelter.com Cache-Control: no-cache
I have tried manually encoding the url but nothing allows the + to work. I have since switched my test email address to use a non + email address format so I can continue working. It would be nice if this bug can be fixed in the next release as it's essential to my testing and was working until I updated my mac APP just today.