okhttp3: cookieJar: how to have saveFromResponse always called with all response cookies - okhttp

It looks like cookieJar.saveFromResponse(...) will not be called if Cookie.parseAll(...) returns an empty Cookie List: (https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/http/HttpEngine.java#L867)
and Cookie.parseAll(...) excludes response cookies based on domain matching and other logic:(https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/Cookie.java#L302)
Is it possible to bypass the Cookie.parse domain matching logic so that cookieJar.saveFromResponse(...) is called with response cookies that haven't been whittled down by domain?

Related

How MVC Controller understands when to respond with redirect (for HTML form) and when with JSON (for API/AJAX requests)

In websites, data can be sent using an HTML form to POST /createUser with a payload in the body, and expect a redirect to some page (for example, to a newly created user) in response. Or you can send the same request using an AJAX request (fetch, axios) and expect a JSON response (in which, for example, the same link to a new user can be a field {”redirectTo”: “/createUser”} along with another response payload).
How to distinguish these requests in the controller from the MVC pattern in order to respond with what the client expects? I see these options:
Create different URLs - one for a request with a redirect, the other with a response in JSON. But here the problem is that they have the same logic, only the view-representation differs.
Common URL, but an additional field in the body or header, in which the client himself will explicitly indicate what kind of response he expects.
A common URL, but the server itself determines from the request headers (for example, Content-Type) where the request was made from and what the client expects. But aren't there some edge scenarios where the server might guess wrong?

Deleting all cookies

I'm having a difficult time deleting all cookies using the following code. What seems to happen is that the domain is changed to append a dot in front of it. Instead of deleting all cookies, I get duplicate cookies with slightly different domains. Is there any way to completely remove all cookies no matter what their domain looks like?
Thanks for any help!
//DeleteCookies deletes all cookies
func DeleteCookies(w http.ResponseWriter, r *http.Request) {
for _, c := range r.Cookies() {
deleted := &http.Cookie{
Name: c.Name,
Path: c.Path,
//Expires: time.Unix(0, 0),
MaxAge: -10,
HttpOnly: c.HttpOnly,
Domain: c.Domain,
Secure: c.Secure,
Value: "",
}
http.SetCookie(w, deleted)
}
}
What you try to do doesn't work well as cookies do not work that way.
The easy things first:
HttpOnly, Domain and Secure: These values are not transmitted in a HTTP client request, these fields of c will always be empty. The client uses these fields to determine whether to send a (Name,Value)-pair in the Cookie header or not but doesn't send these values.
For HttpOnly, Secure (and SameSite) this does not matter as these (and MaxAge and Expires) do not contribute to the cookie identity.
Cookie identity is based on the tripple (Domain,Path,Name) as sent in a SetCookie header. Often Domain and Path are implicit but they do have defined values on the client.
Now to delete a cookie with identity (Domain-X, Path-X, Name-X) you must send a cookie with the same identity (Domain-X, Path-X, Name-X) and MaxAge=-1. But as explained above the cookie you receive doesn't contain Domain and Path.
There are two ways out:
You must know whether your cookies are domain or host cookies and which path they were set for and use that information to delete them. (I would recommend this.)
Delete all possible cookies. Upon a request to path /foo/bar/wuz the cookies from the client might stem from path /, /foo or /foo/bar (if I remember correctly; test and look it up in RFC 6265). So delete the cookie with name "Name-X" for all these paths. Do the same for the Domain attribute which unfortunately is more complicated. Delete the host cookie (Domain=="") and delete the domain cookies (Domain!=""). Make sure to get the right domain name (the effective TLD plus one).
As you see 2 is pretty complicated. But that is how cookies are designed: The server is expected to know what cookies the servers sets i.e. the server is expected to know the cookie identity (Domain,Path,Name) of all its cookies. The responsibility of the client is to send back the appropriate (Name,Value) pair for a certain request only. If the server wishes to delete a cookie it just sets MaxAge of that cookie to -1. Note that "that cookie" is something the server is expected to know and not infer from a client request.

HTTP Requests in Laravel

In Laravel we use routes to deal with HTTP requests from the browser.
We can route a request to a controller, do some logic and then return a response.
Now, we can send in variables encapsulated with braces {} and the response can be anything, so it seems to me that routing through a controller means that the the properties of the different request methods (POST, GET, PUT etc.) are lost.
For example I could send a POST request with URI example/{id} then put in my routes.php file
Route::post('example/{id}','SomeController#SomeAction');
Then I could do something in my controller with the variable $id and send a response.
On the other hand I could send a GET request with URI example/{id} and alter my route to
Route::get('example/{id}','SomeController#SomeAction');
The controller would give the same response.
So, am I right in thinking it does not really matter what request method is used?
Two parts of your question I can identify on a second read-through:
Request methods are not lost. You have access to them with $request->getMethod(). So a GET request will return GET. You also have the method isMethod('GET') available to you, which you could use to get a truthy value which would enable you to return a different kind of response depending on the request type.
With regards to the way you set up your URL, what HTTP verb you use does matter if you're creating a REST-ful web service.
I won't explain away what a REST-ful web service is (you can look it up), here is a couple of points from your example:
If you're getting some data, you ought to be doing a GET request. It is the verb to represent a read from a resource. If you had to send a lot of data - and your intention is to add data, you ought to POST it instead.
The URI should be meaningful in a way that best describes the resource you are manipulating.
Together with the HTTP verb, you can infer the implied action. So if you are POSTing to example/1, I might infer that (and this is a digression, actually) that you are attempting to update record 1 from an example resource. In reality, you would perhaps use the PUT verb (which handles update).
Behind the scenes, Laravel uses a POST request due to browser limitations but treats it as a PUT request server-side.
Of course request type does matter. When you want to hide some request data against user and dont show it in url for example:
?username="Admin"&nick="admin1" then u will use POST otherwise you can use GET. When you want get some data u will use GET but when you want to send some data then you should use POST instead.

Problems setting / reading cookie in django

I'm trying to set a persistent cookie for several consecutive requests. The idea is that if a request does not contain the cookie in the first place, a uuid4 identifier is set in a cookie under 'mykey' and the response is sent. This all happens via requests made to a REST api from a javascript client.
I can see the cookie when inspecting the response on my browser, but if I issue a second request—which should not set a new cookie, as 'mykey' is already populated—the cookie is reset with a new uuid4 identifier.
This is the code:
def some_view(request):
cookie = request.get_signed_cookie('mykey', salt='foobar', default=False)
# do stuff
response = HttpResponse(content='foo')
if not cookie:
value = str(uuid.uuid4())
response.set_signed_cookie('mykey', value, salt='foobar')
return response
Any ideas? Thnx!
A.
With the signed cookies, you are probably running into problems with HTTPOnly. You could try this:
set_signed_cookie(key, value, salt='', httponly=False)

Angular $http.delete request with body

So I looked at this post:
is an entity body allowed for an http delete request
Which seems to indicate that while it is 'ok' to do on some conceptual level, in practice it may not be doable because browsers just ignore it.
I have some express.js authentication middleware I need to get through, and I don't want to attach my user details to url params. All my other requests that need to authenticate attach these details to the body of the request.
Is there some way to force this? I saw some other posts where some people seemed to have success in passing a body with their delete request.
I am running a node/sails back-end. It always logs the body as undefined for a delete request. Is there any way to modify
The sails API pulls the id of the object to delete from the params, so we have to append the id to the url.
But if I want to pass some authentication details in a body for server-side verification before processing the delete request, I can't just stick them in an object as the second parameter of the delete request, like you can with $http.post.
Angular's post method automatically assigns whatever we insert as a second parameter to the body of the request, but the delete method does not.
Angular's $http.delete method does allow us to supply a config object as the second parameter, through which we can get access to the 'data' property. This is the same way post does it through it's second parameter.
So if we need to attach a body to a delete request we can use the following:
$http.delete('/api/' + objectToDelete.id, {data: {id: currentUser().id, level: currentUser().level}});
This will pass the object to delete's id in the url parameter, and my user credentials in the body as an object.
Honestly, everytime a trouble sounds like a "restriction of as REST", a rethink of the strategy and the philosophy might be a good idea.
I have some authentication middleware I need to get through
I don't want to attach my user details to url params
I'm not directly answering the question, but you should know that among the commons
URL parameters (or query, but URL anyway)
Body
there is a third option for "passing values to the server" :
request Headers
I'd just suggest to consider that third option to provide your credentials: request header.
Edit : following appendix would just apply to any "external" middleware, like a proxy server or whatever, not a true express middleware inside sails.js
In addition, that would be a good idea that your middleware stripped those headers before redirecting to the real action.

Resources