encode request.query in express - node.js

I wrote a simple API to return requset.query in response.
Sample Url:
http://localhost:8082/redirect?requesttype=click&id=79992&redirectto=http://localhost:8081/redirect?name=john&id=123
This returns following response,
but on passing encoded Url things are working as expected(screenshot attached),
http://localhost:8082/redirect?requesttype=click&id=79992&redirectto=http%3A%2F%2Flocalhost%3A8081%2Fredirect%3Fname%3Djohn%26id%3D123
But our API is getting utilized by various customers, is there any method in express.js where I can automatically encode the Url and serve the request as expected.

Related

Mocking response NightWatch + Selenium NodeJS

Trying to mock a response on my test (there is no mock server since i only have to mock twice)
Im using NightWatch over selenium in reactJS
I need to mock a post and a get request.
the post request is for a known static URL
but the GET one is for a url with a random query inside it like: ?id=example
i managed to mock the post one with NightWatch command .mockNetworkResponse() once, but now its not working for some reason, and the GET one is a bit more complicated since in the url there is a query passed like
?id=example which is random.
For some reason the .mockNetworkResponse() is not able to capture it. Ive tired using nock but i cant seem to figure out how to make it work i think its not even performing the nock action when i call for the request
//pre defined command to perform the search that triggers the post request
browser
.searchSpesific('jfk', 'lax',true);
//the command that used to work but now dosn't
browser
.mockNetworkResponse("https://example.com/search",{
status: 200,
headers:{
'Content-Type': 'UTF-8'
},
body: 'intercepted'
})
the GET request URL looks like this:
https://example.com/search?id=randomIdString

Express routing giving 404 when receving params

I'm working with Express Router, and I'm trying to get some information from params URL, but I cannot make it works as it always returned me a 404.
This is the URL I'm trying to call
http://localhost:8080/api/v1/contr/method?param1=value1&param2=param2
And in my express router I have:
this.router.get("/contr/method", JWT.authenticateJWT, ContrController.method.bind(ContrController));
And I always get
finalhandler default 404 +2m
If I send the request without params the app work as expected:
http://localhost:8080/api/v1/contr/method
If you're building a URL with a URL itself as a parameter, then you need to call encodeURIComponent() on the embedded URL:
let url = "http://localhost:8080/api/v1/contr/method?url=" + encodeURIComponent(otherUrl);
This encodes the parameter in a way that will not be confused with the path of the URL during URL parsing. See doc on encodeURIComponent() for more info.
You need to use encodeURIComponent() on any parameter that contains characters that are special when it comes to URL parsing. They will then be encoded in hex such as %2F which will cause them to not match any of the URL parsing. And, the URL parsing in Express already automatically decodes them for you.

Firebase bucket / axios url in request body decoding issue

Interesting issue when using Firebase buckets and axios in a JS environments.
When I upload a file into a bucket and send the file link returned by firebase to server in a request body, the link is auto decoded in the server.
Upload a file to bucket from web
Firebase returns a link: https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[POINTER]%2Fimages%2F[FILE_NAME])
note the url encoded %2F that firebase uses around the 'images'
Save this to DB via a Cloud Function call by using axios.post()
Using headers: {'Content-Type': 'application/x-www-form-urlencoded'} due to Cloud Function limitations here. The url is nested in a JSON object as a String.
When this request is picked up in the Cloud Function, the URL in the object has been automatically urldecoded, resulting in:
https://firebasestorage.googleapis.com/v0/b/[BUCKET_NAME]/o/[POINTER]/images/[FILE_NAME])
note the / around the 'images'
Problem: Firebase doesn't return the file when %2F is replaced with / in the URL, only returning error:
Invalid HTTP method/URL pair.
I understand that I have only one option here, and it is to prevent this String to be URL decoded during the client-server axios call. Since I am using the mentioned headers, I'm not sure how this can be achieved.
Side quest: Why does Firebase enforce the urlencode this strongly and doesn't return the file independently of the representation of the path to file (encoded or not)?

Postman Requests Receive a HTTP 401 Status Code

I am working on creating a Node.js REST API, using the Express module, that redirects HTTP GET and PUT requests to another server. However, when running test queries in Postman, I always get HTTP 401 Unauthorized responses. Yet, when I try the same on query on the Chrome browser I get a successful response (HTTP 302). I read through some documentation on the HTTP request/response cycle and authorization. The server I am redirecting to uses HTTP Basic authentication. In my code I am redirecting the API call to my application server using the res.redirect(server) method. In my Postman request I am setting the username/password in Authorization tab for my request. I know this is gets encoded using base64, but I am guessing this isn't being passed on the redirect when done through Postman.
The following code snippets show what I've created thus far.
This is the Express route I created for GET requests
app.get('/companyrecords/:name', function(req, res) {
var credentials = Buffer.from("username:password").toString('base64');
console.log(req);
var requestURL = helperFunctions.createURL(req);
res.redirect(requestURL);
});
I define a function called createURL inside a file called helperFunctions. The purpose of this function is set up the URL to which requests will be directed to. Here is the code for that function.
module.exports.createURL = function (requestURL) {
var pathname = requestURL._parsedUrl.pathname;
var tablename = pathname.split("/")[1];
var filter = `?&filter=name=\'${requestURL.params.hostname}\'`;
var fullPath = BASE_URL + tablename.concat('/') + filter;
console.log(fullPath);
return fullPath;
}
Where BASE_URL is a constant defined in the following form:
http://hostname:port/path/to/resource/
Is this something I need to change in my code to support redirects through Postman or is there a setting in Postman that I need to change so that my queries can execute successfully.
Unfortunately you can't tell Postman not to do what was arguably the correct thing.
Effectively clients should be removing authorisation headers on a redirect. This is to prevent a man-in-the-middle from sticking a 302 in and collecting all your usernames and passwords on their own server. However, as you've noticed, a lot of clients do not behave perfectly (and have since maintained this behaviour for legacy reasons).
As discussed here however you do have some options:
Allow a secondary way of authorising using a query string: res.redirect(302, 'http://appServer:5001/?auth=auth') however this is not great because query strings are often logged without redacting
Act as a proxy and pipe the authenticated request yourself: http.request(authedRequest).on('response', (response) => response.pipe(res))
Respond with a 200 and the link for your client to then follow.

How to send a http response using koajs

I'm trying to validate a webhook via facebook. So facebook hits my url my-url/facebook/receive within my route in nodejs i'd do res.send(req.query['hub.challenge']); to send an http response.
I'm using KoaJS. From what i understand, Koajs merges the request and response object into ctx but when reading through the docs I can't find anything along the lines of ctx.send or similar to send a http response.
Can anyone give me some direction or links.
Thanks.
To send the body of a response, you can simply do ctx.response.body = 'Hello'. There are many aliases attached to ctx, so you don't necessarily have to reference the response or request yourself. Doing ctx.body = 'Hello' would be the same as the code above.
If you wanted to set headers, you would use the ctx.set() method. For example: ctx.set('Content-Type', 'text/plain').
To access the query parameters, you would use ctx.request.query['some-key'] (or simply the alias ctx.query['some-key']).
All of the different request/response methods are documented pretty well at the Koa website along with a list of aliases attached to ctx. I highly recommend you give it a read.

Resources