How to set TCP_NODELAY and SO_KEEPALIVE with HttpClient 4.3 - apache-httpclient-4.x

With Apache HttpClient 4.3 how do I turn off Nagle's algorithm (TCP_NODELAY) and turn on TCP keep-alive packets (SO_KEEPALIVE) without using the deprecated HttpParams?
Note: TCP keep-alive and HTTP keep-alive are two different things.

SocketConfig socketConfig = SocketConfig.custom()
.setSoKeepAlive(true)
.setTcpNoDelay(true)
.build();
CloseableHttpClient client = HttpClients.custom()
.setDefaultSocketConfig(socketConfig)
.build();

Related

CouchDB _session not returning cookie

Environment:
CouchDB 2.2.0 running on VirtualBox, running up-to-date Debian image. Network type is bridged, all ports are open, no https.
Vue3.js app (not using any Vue functionality to access the DB)
Remote access JS package:
axios
fetch
Browser: Chrome latest
Relevant CouchDB local.ini settings
[couch_peruser]
enable = false
delete_dbs = false
[chttpd]
port = 5984
require_valid_user = false
proxy_use_secret = false
bind_address = 0.0.0.0
authentication_handlers = {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, default_authentication_handler}
[httpd]
bind_address = 127.0.0.1
enable_cors = true
(default authentication handlers set in default.ini)
authentication_handlers = {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}
[couch_httpd_auth]
secret = (hash num)
require_valid_user = false
allow_persistent_cookies = true
[cors]
origins = *
headers = accept, authorization, content-type, X-Auth-CouchDB-UserName, origin, referer
credentials = true
methods = GET, PUT, POST, HEAD, DELETE
What Happens
If I do the query via curl, I get a cookie in the response.
Here's the curl call:
curl -v http://couchman.lcldev:5984/_session \
-H "Content-Type:application/json" \
-H "X-Auth-CouchDB-UserName:<uname>" \
-d '{"name":"<uname>","password":"<passwd>"}'
And here's the response:
< HTTP/1.1 200 OK
< Cache-Control: must-revalidate
< Content-Length: 47
< Content-Type: application/json
< Date: Wed, 10 Oct 2018 21:16:10 GMT
< Server: CouchDB/2.2.0 (Erlang OTP/19)
< Set-Cookie: (cookie info)
<
{"ok":true,"name":"<name>","roles":["<roles>"]}
Yay. I get a cookie.
But if I call it from within my app (with either fetch or axios), I only get these headers:
Response headers:
cache-control,must-revalidate
content-type,application/json
server,CouchDB/2.2.0 (Erlang OTP/19)
No Set-Cookie header.
So, what's up? What am I missing?
Answered in first comment - see thread for more info.

Error when accessing rest service from WebExtension using XMLHttpRequest

I am trying to access a rest service that I am hosting on an amazon AWS server from a firefox WebExtension.
I have registered a background script in the manifest.json which then tries to access the service.
"background": {
"scripts": ["OwnerLangBackground.js"]
},
"permissions": [
"*://ec2-35-158-91-62.eu-central-1.compute.amazonaws.com:9000/*"
]
However, the XMLHttpRequest just returns an error but I don't see what goes wrong. While researching this issue, I stumbled across the following page:
https://mathiasbynens.be/notes/xhr-responsetype-json
Replacing my own code with a (slightly modifed) copy of the code from the above link I now have:
// OwnerLangBackground.js
console.log("OwnerLangBackground.js loaded");
var getJSON = function(url, successHandler, errorHandler) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.onreadystatechange = function() {
var status;
var data;
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
if (xhr.readyState == 4) { // `DONE`
status = xhr.status;
if (status == 200) {
data = JSON.parse(xhr.responseText);
successHandler && successHandler(data);
} else {
errorHandler && errorHandler(status, xhr.responseText);
}
}
};
xhr.send();
};
/* BLOCK 1: removing the comments for this block works
getJSON('https://mathiasbynens.be/demo/ip', function(data) {
console.log('Your public IP address is: ' + data.ip);
console.log('Your response is: ', data);
}, function(status) {
console.warn('Something went wrong.', status);
});
*/
/* BLOCK 2: removing the comments for this block, does not work
getJSON('http://ec2-35-158-91-62.eu-central-1.compute.amazonaws.com:9000/get-languages', function(data) {
console.log('Your response is: ', data);
}, function(status) {
console.warn('Something went wrong.', status);
});
*/
Strangely enough, activating BLOCK 1 works as expected (ip address obscured on purpose).
OwnerLangBackground.js loaded
Your public IP address is: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xx
Your response is: Object { ip: "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:…" }
Activating BLOCK 2 results in the error response.
OwnerLangBackground.js loaded
Something went wrong. 0
However, if I call the two URLs using curl directly, they both return valid JSON:
> curl https://mathiasbynens.be/demo/ip
{"ip":"xxxx:xxxx:xxxx::xxx"}
> curl http://ec2-35-158-91-62.eu-central-1.compute.amazonaws.com:9000/get-languages
[{"language":"??"},{"language":"de"},{"language":"en"},{"language":"fr"},{"language":"it"}]
I have added debugging output to my rest service on the AWS server and I see that it gets called. I also traced the WebExtension call to the rest service using Wireshark on my local machine on which the WebExtension is running and I can see the JSON string being returned, so I am guessing that the error occurs somewhere within firefox/the webextension, but I am at a total loss.
Things I have considered:
Permissions in the manifest: as far as I can tell the URL pattern for my aws-url is correctly added. However, the call to mathiasbynens.be works even though I have not added the url to the permissions
the call that works uses https while the call that does not work uses http. Could this be the reason?
Can anyone point me in the right direction to get more feedback on what goes wrong? I've tried adding a onerror callback to the xhr request. It is called but as far as I can see doesn't provide more information.
UPDATE:
I've come up with two more ideas. Using curl -v provided me with the headers:
> curl -v http://ec2-35-158-91-62.eu-central-1.compute.amazonaws.com:9000/get-languages
* Hostname was NOT found in DNS cache
* Trying 35.158.91.62...
* Connected to ec2-35-158-91-62.eu-central-1.compute.amazonaws.com (35.158.91.62) port 9000 (#0)
> GET /get-languages HTTP/1.1
> User-Agent: curl/7.38.0
> Host: ec2-35-158-91-62.eu-central-1.compute.amazonaws.com:9000
> Accept: */*
>
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 23 Apr 2017 06:43:42 GMT
<
* Connection #0 to host ec2-35-158-91-62.eu-central-1.compute.amazonaws.com left intact
[{"language":"??"},{"language":"de"},{"language":"en"},{"language":"fr"},{"language":"it"}]
> curl -v https://mathiasbynens.be/demo/ip
* Hostname was NOT found in DNS cache
* Trying 2a01:1b0:7999:402::144...
* Connected to mathiasbynens.be (2a01:1b0:7999:402::144) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server key exchange (12):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* Server certificate:
* subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.mathiasbynens.be
* start date: 2015-07-28 00:00:00 GMT
* expire date: 2018-08-12 23:59:59 GMT
* subjectAltName: mathiasbynens.be matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
> GET /demo/ip HTTP/1.1
> User-Agent: curl/7.38.0
> Host: mathiasbynens.be
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 23 Apr 2017 06:44:16 GMT
* Server Apache is not blacklisted
< Server: Apache
< Access-Control-Allow-Origin: *
< Strict-Transport-Security: max-age=15768000; includeSubDomains
< Vary: Accept-Encoding
< Cache-Control: max-age=0
< Expires: Sun, 23 Apr 2017 06:44:16 GMT
< X-UA-Compatible: IE=edge
< X-Content-Type-Options: nosniff
< X-Frame-Options: DENY
< X-XSS-Protection: 1; mode=block
< Transfer-Encoding: chunked
< Content-Type: application/json;charset=UTF-8
<
* Connection #0 to host mathiasbynens.be left intact
{"ip":"xxxx:xxxx:xxxx::xxx"}
The one difference that stuck out was that my rest service's response lacks the Transfer-Encoding and Access-Control-Allow-Origin? headers, so I'll look into adding those.
Still, if anyone has a hint on how to get more error information for what goes wrong with XmlHttpRequest I'd be glad to hear it.
Ok, it seems the missing Access-Control-Allow-Origin? header was the root of my problems.
I have now changed all methods in my Spring-RestControllers by adding another method parameter HttpServletResponse response and then calling setHeader() on that parameter.
#RequestMapping("/get-languages")
public #ResponseBody List<Language> getLanguages(HttpServletResponse response) {
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "*");
return languageRepository.findAll();
}
Now my WebExtension can use this rest service sucessfully using XmlHttpRequest.
It would have been helpful if this information (that the CORS header was missing) had been visible somewhere in firefox's debugging or js console, so if anyone can tell me how I could have seen this, I'd still appreciate a hint.

Understanding curl POST request command that contains multiple Content-Type headers

The following curl command:
curl -v -F 'json={"method":"update_video","params":{"video":{"id":"582984001","itemState":"INACTIVE"},"token":"jCoXH5OAMYQtXm1sg62KAF3ysG90YLagEECDAdlhg.."}}' https://api.somewebservice.com/services/post
Produces this output:
{"method":"update_video","params":{"video":{"id":"55269001","itemState":"INACTIVE"},"token":"jCoXH1sg62KAF3ysG90YLagEECTP16uOUSg_fDAdlhg.."}}' https://api.somewebservice.com/services/post
* Trying 64.74.101.65...
* Connected to api.somewebservice.com (64.74.101.65) port 443 (#0)
* TLSv1.0, TLS handshake, Client hello (1):
* TLSv1.0, TLS handshake, Server hello (2):
* TLSv1.0, TLS handshake, CERT (11):
* TLSv1.0, TLS handshake, Server key exchange (12):
* TLSv1.0, TLS handshake, Server finished (14):
* TLSv1.0, TLS handshake, Client key exchange (16):
* TLSv1.0, TLS change cipher, Client hello (1):
* TLSv1.0, TLS handshake, Finished (20):
* TLSv1.0, TLS change cipher, Client hello (1):
* TLSv1.0, TLS handshake, Finished (20):
* SSL connection using TLSv1.0 / DHE-RSA-AES256-SHA
* Server certificate:
* subject: OU=Domain Control Validated; OU=Issued through Somewebservice Inc. E-PKI Manager; OU=COMODO SSL; CN=api.brightcove.com
* start date: 2015-09-02 00:00:00 GMT
* expire date: 2016-10-09 23:59:59 GMT
* subjectAltName: api.somewebservice.com matched
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
> POST /services/post HTTP/1.1
> User-Agent: curl/7.41.0
> Host: api.somewebservice.com
> Accept: */*
> Content-Length: 294
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------5106835c8f9f70f9
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Content-Type: application/json;charset=UTF-8
< Content-Length: 943
< Date: Sun, 10 Apr 2016 22:29:23 GMT
< Server: somewebservice
<
* Connection #0 to host api.somewebservice.com left intact
{"result": {"id":55225001,"name":"Taxpayers pay to cover tattoos","adKeys":null,"shortDescription":"Opening statements are set to begin in the trial.","longDescription":null,"creationDate":"1260220396","publishedDate":"12603101609","lastModifiedDate":"1460352526","linkURL":null,"linkText":null,"tags":["Crime","national","wtsp","neo-nazi","court","taxpayers","News","David","john"],"videoStillURL":"http:\/\/bcdownload.net\/wtsp\/35134001\/3508134001_55110080001_59001.jpg?pubId=35134001","thumbnailURL":"http:\/\/bcdownload.edgesuite.net\/wtsp\/87134001\/350134001_55110081001_th-55100159001.jpg?pubId=35084001","referenceId":"7cf007503e2ee37a","length":112106,"economics":"AD_SUPPORTED","playsTotal":248,"playsTrailingWeek":0}, "error": null, "id": null}
There are two 'Content-Type' objects in the above output:
> Content-Type: multipart/form-data;
and
< Content-Type: application/json;charset=UTF-8
According to the docs, using -F allows curl to send data as a multi-part form, but then the json= is something I can't find in the docs. I'm assuming it's converting the dictionary/string:
{"method":"update_video","params":{"video":{"id":"582984001","itemState":"INACTIVE"},"token":"jCoXH5OAMYQtXm1sg62KAF3ysG90YLagEECDAdlhg.."}}
to JSON? Or more precisely, it's adding the 'Content-Type': 'application/json' header to the POST request? So is this essentially a POST request with two distinct headers?
The first Content-Type header is part of the client's request header and the second one is part of the server's response header. The request and the response are separated by 2 CRLFs. Request and response each have their own Content-Types.

Why does the client not accept my WebSocket response handshake?

I use Chrome 14. This is my python websocket server code snippet:
global guid
key = hashlib.sha1(headers['Sec-WebSocket-Key']+guid).digest()
key.encode('iso-')
headers['Sec-WebSotycket-Accept'] = base64.b64encode(key)
print headers['Sec-WebSocket-Accept']
handshake = '\
HTTP/1.1 101 Switching Protocols\r\n\
Upgrade: %s\r\
Connection: %s\r\
Sec-WebSocket-Accept: %s\r\
Sec-WebSocket-Protocol: base64\r\
' %(headers['Upgrade'],headers['Connection'],headers['Sec-WebSocket-Accept'])
try:
self.conn.send(handshake)
except Exception as e:
print e
Why does the Chrome client not accept this server send handshake?
Request URL:ws://127.0.0.1:1234/
Request Headers
Connection:Upgrade
Host:127.0.0.1:1234
Sec-WebSocket-Key:xuV2xuiXxqL4Hwcxjg9dJA==
Sec-WebSocket-Origin:null
Sec-WebSocket-Version:8
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Could it be line 4 of your server code? Your key "Sec-WebSotycket-Accept" looks misspelled.

Cannot receive JSON exception message/content type on remote requests

I have a ASP.NET MVC3 application, which uses JSON to comunicate with a Flash UI.
I´m use an ActionFilterAttribute to handle JSON exceptions (from Handle JSON Exceptions Gracefully in ASP.NET MVC 2: http://www.dotnetcurry.com/ShowArticle.aspx?ID=496):
public class HandleJsonExceptionAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.Result = new JsonResult()
{
JsonRequestBehavior = JsonRequestBehavior.AllowGet,
Data = new
{
filterContext.Exception.Message,
}
};
filterContext.ExceptionHandled = true;
}
}
}
It´s works ok when executes on localhost, details from fiddler:
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 11 Apr 2011 19:05:21 GMT
Content-Length: 34
{"Message":"No está autenticado"}
But, when executed from remote clients, on the LAN for example, I get the response in "Content-Type: text/html" instead "Content-Type: application/json;" and the content is a standard html error page:
500 - Internal server error.
There is a problem with the resource you are looking for, and it cannot be displayed.
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 11 Apr 2011 19:07:53 GMT
Content-Length: 1208
What or where I need to configure something to get the JSON response on remote requests?
I need the flash UI receive a http 500 error, but with the json message instead the html.
Looking at the article the javascript only seems to be wire up for local requests.
What you need is to be using jsonp. (json with padding). This will allow you to do proper cross domain request returning a json object.
Further info can be found here and here.
I had a same problem, I solved with this code in web.config
<httpErrors existingResponse="PassTrough"></httpErrors>