-
Notifications
You must be signed in to change notification settings - Fork 237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added CookieJar for storing all cookies on redirects #129
Conversation
…ookies config added. Defaults to false)
Hey @icemilo, thanks for the PR. I don't mind adding "cookie jar" support into Needle (it seems like a few lines of code away), but I wouldn't do it using a global variable, because this makes it very unclean as you would easily share cookies across different requests. I think I'd prefer users to pass in explicitly the cookie jar they wanted to use for a specific request, e.g.: var needle = require('needle'),
jar = {};
needle.get('foobar.com/path', { cookie_jar: jar }, function(err, resp) {
console.log(jar); // { cookie1: 'something' }
needle.get('foobar.com/whatever', { cookie_jar: jar }, function(err, resp) {
console.log(jar); // { cookie1: 'something', cookie2: 'something_else' }
})
}) Or maybe you could even use needle.defaults({ cookie_jar: jar });
needle.get('foobar.com/path', function(err, resp) {
console.log(jar); // { cookie1: 'something' }
needle.get('foobar.com/whatever', function(err, resp) {
console.log(jar); // { cookie1: 'something', cookie2: 'something_else' }
})
}) I haven't tested this yet, but it might work. |
Will this be implemented? |
Hey @icemilo, sorry I've taken so long to look into this. Your PR looks good for merging but I'm trying not to merge major changes without including tests. Would you be willing to add one or two so I can get this into master? :) |
@tomas Alright, now that you've come back from a long journey, I will include tests when I have some time to work this one. It should not take long ;) |
Cool, thanks mate. |
…in options, Fixed bug where cookies are not stored in cookie jar in the last redirected page
@tomas Could you check my commits for tests and see if it satisfies? :) |
@icemilo Looks good. I think I'll tweak the syntax a bit but everything seems OK. 👍 |
@tomas Alright, thanks for considering this PR to be merged :) Have a great New Year's eve 👍 |
Can't this be implemented using only In my opinion, it would make more sense if We could pass redirect cookies to the next request and then store them in the |
@rchipka I was actually in the process of getting this merged and got to the same conclusion. My only doubt is whether you'd always want to have all of the redirect cookies stored and not just the last ones. |
@tomas I think that res.cookies should essentially reflect the current Cookies header, which would include any of the previously acquired redirect cookies according to the I think that if needle were to have a global cookie jar, it should at least be a fully featured one. For example, it should be domain specific instead of just sending all the global cookies along in every request. It also shouldn't require any additional options. |
@rchipka Thanks for the opinion. I needed this feature because long ago, I came across some endpoints which would redirect to another endpoint about 3 times and each endpoint needed all the cookies on redirects. Because |
# Conflicts: # lib/needle.js
@icemilo I think that users should configure options (including cookies) via the global default options or per-request options. Giving the request function the same cookie object that the developer provided has no added benefit over the developer just setting any cookies in a global or per-request fashion. It'd be different if the developer gave a more sophisticated cookie object that needle could interact with to resolve domain specific cookies etc. I'm not advising we go that route either as it adds even more complexity than requiring the developer to provide the cookie object as an option in the first place. I just see no reason why the developer wouldn't just use the I think that we should choose one method and one option. |
@rchipka If we would want to go with overriding defaults option then it would make more send if we have a global variable in Needle which acts as a Again, the reason why developers would not just use From your points, I'm positive for having domain specific cookie jars and I think this can be an improvement later on. I hope this makes it more clearer. |
@icemilo I guess my point is that the The issue seems to be access to the cookies. The redirect cookies are completely inaccessible to the developer, and while a global The developer has no way, via a simple While a developer would be able to modify the global cookies using this The solution to this would be to have the previous endpoint pass any cookies to the next endpoint. Then, if the developer wants to update the "cookie jar" with any new cookies, they would simply copy the cookies from This would allow any developer to access any cookie and do anything with it that they choose, without adding any options/overhead/confusion/complexity. It's the way I'd expect Needle to work. |
@rchipka this feature is not enabling developers to view and edit cookies. It's for the endpoints after, for example, 3 redirects needing cookies from the first endpoint. Because redirects are internally done in Needle, the third endpoint does not get the cookies from the first endpoint. And this is the only reason for cookie jar feature. |
@icemilo That's true, however this feature would imply to the developer that they can have some sort of control to view and edit the cookies because they have to manually set an option with a cookie jar object. My point is, why not skip both of these things and simply pass along the cookies after each redirect. This way redirects 2 and 3 would receive all the cookies from redirect 1. Redirect 3 would receive all the cookies from redirect 1 and 2, etc. And then, after all the redirecting has finished, the developer could see all the cookies from all the redirects inside of This is the way I would expect Needle to work by default when using the |
After a discussion with my pillow I think I agree that the default behaviour when setting @icemilo Would you adapt your code so we can get this merged? (And thanks for the discussion!) |
@tomas Thanks for the decision(I know it would've been tough for you!) I will adapt my code soon and let you know. |
@icemilo Any news? I can take it from here if you prefer. :) |
@tomas Hey, sorry to keep you waiting there. Its been a really busy days for me and finally done with it today(finally pushing to production tomorrow!) So I guess I can finish by this week. Thanks for your patience! |
C'mon, such an easy fix taking so long. |
@smartpunter You're right. I'll do the final changes when I have a minute. Thanks for the heads up! |
@tomas Hey there, sorry for delaying this PR for too long. I have been really busy these few months. Anyways, I have updated the code, could you take a look? Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@icemilo 👍 Thanks for updating this. I've made a few suggestions in my review.
@tomas The suggestions aren't anything major, so if the tests are passing and everything works this could be okay to merge as-is. However, I recommend you take a look and them and decide if any of the changes should be made before merging this.
@@ -415,7 +419,11 @@ Needle.prototype.send_request = function(count, method, uri, config, post_data, | |||
set_timeout(config.read_timeout); | |||
|
|||
if (headers['set-cookie'] && config.parse_cookies) { | |||
resp.cookies = cookies.read(headers['set-cookie']); | |||
if (redirect_cookies !== null) { | |||
resp.cookies = Object.assign(redirect_cookies, cookies.read(headers['set-cookie'])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: Object.assign() not available before Node v5
|
||
if (config.follow_set_referer) | ||
config.headers['referer'] = uri; // the original, not the destination URL. | ||
|
||
config.headers['host'] = null; // clear previous Host header to avoid conflicts. | ||
|
||
debug('Redirecting to ' + url.resolve(uri, headers.location)); | ||
return self.send_request(++count, method, url.resolve(uri, headers.location), config, post_data, out, callback); | ||
return self.send_request(++count, method, url.resolve(uri, headers.location), config, post_data, out, cookies.read(headers['set-cookie']), callback); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using cookies.read() again here, why not just use resp.cookies
directly?
if (config.follow_set_cookies && resp.cookies) | ||
config.headers['cookie'] = cookies.write(resp.cookies); | ||
if (config.follow_set_cookies && resp.cookies) { | ||
config.headers['Cookie'] = cookies.write(Object.assign(resp.cookies, cookies.read(headers['set-cookie']))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me this could all be consolidated on line 422. If the user wants to follow_set_cookies
, then parse_cookies
has to be true anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. No need to re-parse the header.
Ok, I took @icemilo's code and refactored it to remove duplication and support older versions of Node (where Object.assign is not available). I also made sure that if the last request (non-redirect) doesn't contain cookies, |
@tomas Good catch. Glad this issue is resolved. Hopefully no response cookies are lost anymore! |
Hi, I love needle which simplifies http requests.
I needed to store all the cookies for future request to the same origin, but needle only stores the latest cookie from the last redirect.
I thought someone else might need this feature so I created a pull request.
I've added a global variable to store all the cookies site sets on redirects and requests with cookies saved in the global
cookieJar
. And also, I have added a config key asfollow_set_all_cookies
defaults tofalse
. Also, addedexports.cookies
for future needle requests.