Lets say my client (Browser) request my java service (Service A).
http://localhost:8080/getDataFromB
Based on the request, from my Service A, I need to make another HttpRequest to either Service B or Service C to get the data.
getDataFromB: http://serverb.com/getDataFromB
getDataFromC: http://serverc.com/getDataFromC
I tried making HttpRequest to Service B and Service C based on the request. But should I do it ? or Should I forward the requests the service B or Service C ? If So I save some TCP connection requests on my side.
What will be difference between making HttpRequest vs forwarding the requests
If you don't want your client to know that you're actually serving the response from B or C, you should forward the request to either B or C.
If you want your client to know that your server will not be handling A directly, but instead will do B or C – so perhaps in the future the client can ask for B or C directly instead of asking for A – then you should send a redirect to the client.
You could instead do what you're suggesting - your server handles incoming request, then makes a separate HTTP request to B or C – but that would just add more complexity to how your server communicates back with the original client. If your server logic somehow "fits" with this approach, I would consider stepping back and re-thinking your server logic to either handle requests directly, or handle it with either a redirect or forward.
Unless your server is unable to handle new inbound requests due to excessive TCP connections, I wouldn't worry about optimizing for that.
Related
Recently I came with an issue consuming and posting to an API made under the stack of (Java,Apache- Service B) which that service sends request to my service (Express-Serivce A) and this was happening:
Service B sends notification to Service A
Service A respond only HTTP CODE 200 (With no content. just plain status code).
Service B request fails to Error 504 Request Timed Out.
Service B proceeds to send the same request multiples times due to failure.
After troubleshooting (I have no access to Service B source code), I added a response body alongside the statusCode to my Service (service A) to be like this:
** response.status(200).send('OK') **
After that change Service B was able to catch a successful response from Service A.
So in summary my question would be: Does Java,Apache stack expect for a response body to confirm the HTTP Response? or Does Service B code is not properly catching responses from other services? or maybe it's service B source code who's requiring for a Response Body to be filled.
Details above.
I have a use-case where A calls B, and B calls C via REST APIs(A->B->C). B is a thin orchestrator where the sole responsibility is to route request to C and sends back response from C to A as it is.
I tried to send back the http response from C to A as it is without any manipulation, by completely avoid constructing response(jax-rs)in system B.
The issue is that response received at A does neither have any data or response body nor headers.
Questions & Clarifications :
Are the scope of http request and response specific to each http call?
What is the solution ?
The Oracle GSSAPI Java examples, and various SPNEGO / GSSAPI IETF RFCs indicate that both the GSS initiator (client) and acceptor (server) should have a loop to establish a security context, and that the client may need to make multiple passes with GSS tokens before the security context is established.
Oracle GSSAPI example:
https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/BasicClientServer.html
Structure of the Generic Security Service (GSS) Negotiation Loop:
https://www.rfc-editor.org/rfc/rfc7546
SPNEGO-based Kerberos and NTLM HTTP Authentication in Microsoft Windows:
https://www.rfc-editor.org/rfc/rfc4559
For instance RFC4559 gives this example:
Pass 1: Fails because request does not have a token:
C: GET dir/index.html
S: HTTP/1.1 401 Unauthorized
S: WWW-Authenticate: Negotiate
Pass 2: Fails, but request has a token
C: GET dir/index.html
C: Authorization: Negotiate a87421000492aa874209af8bc028
S: HTTP/1.1 401 Unauthorized
S: WWW-Authenticate: Negotiate 749efa7b23409c20b92356
Pass 3: Succeeds
C: GET dir/index.html
C: Authorization: Negotiate 89a8742aa8729a8b028
S: HTTP/1.1 200 Success
S: WWW-Authenticate: Negotiate ade0234568a4209af8bc0280289eca
Here the security context is established and thus the request is authenticated on the third pass. i.e. on the second pass from the client (C) to server (S) with a token.
Question 1:
Why might multiple passes from initiator to acceptor with tokens be required before the security context is successfully established?
Why might pass 2 above fail, but pass 3 succeed?
Does something change on either the initiator or the acceptor between these 2 passes?
Question 2:
My instinct is that both the initiator and acceptor loops should have protection against endless looping.
For instance the initiator could abort if the context is not established by x attempts.
Are there any rules-of-thumb / metrics on the number of passes that might reasonably be expected to establish the security context?
e.g. if the security context has not been established by the 5th pass --> abort.
Question 3:
In the Oracle GSSAPI examples the client and server communicate over sockets.
The server builds a GSSContext object which is dedicated to a single client, is kept until the server closes, and is thus available for multiple passes to establish the security context.
But how might this work for a Http RESTful WebServer with multiple clients?
My assumption is that:
a) each pass of a request to establish a security context should be made to the same GSSContext object (and not against a new GSSContext instance).
b) the Http server should establish a new GSSContext instance for each new client request.
(i.e. a GSSContext object should not be shared / reused across multiple clients / requests).
If my assumptions are correct the server must distinguish between:
i) a following pass for an existing request for which the security context has not yet been established. --> an existing GSSContext object and loop should be used.
ii) the first pass of a totally new request (either from the same or from a different client). --> a new GSSContext object and loop should be used.
Using Negotiate as the example protocol, it's useful to consider how it operates.
The server indicates to the client that it can support negotiation.
The client agrees and infers what the server might support.
The client creates a token based on what it really thinks the server supports (e.g. Kerberos), and then creates a list of other possible token types (e.g. NTLM).
The client sends both the token and list to the server.
The server either accepts the initial token or decides to pick something else from the list.
The server indicates to the client that it wants something else.
The client then sends another token of the preferred type.
The server accepts or declines and responds to the client appropriately.
This requires up to three roundtrips and may fail or complete after one. Other protocols may choose to do whatever they want.
You will probably want to track the number of roundtrips and kill it after a arbitrarily high number. The resources required aren't that high, but under load it can exhaust the system.
I would like to create a web application that is able to "ping" the client once the client has accessed certain URL (e.g. www.example.com/ping/hello) in order to get the round trip time between server and client. And by "ping" request i mean a simple request with a timestamp from server and client sends back response with its timestamp. I was hoping for this activity to be done with a single URL if possible.
The flow is something like this:
Client goes to the URL
Server sends the response to the client with its timestamp
Client then sends another response to server with new timestamp
Server finally concludes the connection with 200 OK
So far I've only been able to do the first and second steps but not sure how to ensure client to go to the same URL again without back to the first step.
My server code is something like this:
#GET
#Path("/helloping")
public Response getPingServerClient(#Context HttpServletRequest req) {
String result = Long.toString(System.currentTimeMillis());
return Response.status(200).entity(result).build();
//the code to receive the response from client containing timestamp
}
Is there a way to do that?
There are two client to server calls. You'll have to figure out a way to differentiate between these two calls.
I can think of 3 options for this purpose:
HTTP header
Query parameter in GET request
POST request with a marker to differentiate the two calls
The request/response flow will be something like this:
Client -> Server : Request
Server -> Client : Response with timestamp t1
Client -> Server : Request with timestamp t2 and the above mentioned marker
Server -> Client : Response 200
In this approach, you'll have to write custom code at both server and client side to handle the mentioned logic.
I'm not a fan of what you are proposing because you're basically forcing the client to setup up code to effectively become a server, itself. This is inconvenient for the client.
Instead, consider a ping-pong approach where the client first calls the server's ping endpoint, which returns the server's timestamp. As soon as the client obtains the server's ping response, the client is instructed to call a second pong method, which accepts the new timestamp.
It's easier and simpler to require the client to call web service methods than it is to force to client to become a pseudo server. Hence the recommendation.
I have a service that gets requests from many clients and after some processing sends a response to the clients. I use a ThreadPoolExecutor (threadExecuterClient) to handle client requests and put them in a BlockingQueue (requestQueue). Many clients can send concurrent requests. I have another ThreadPoolExecutor (threadExecuterServer) that processes requests in requestQueue. This processing is basically consists of send that request to a server and get response. After processing, I need to send that response to the client which has made that request. I am having difficulties to track which client has made which request. I basically need to find a way to map the client request to the result of processing. The service will be like a gateway.
Any idea to handle this issue is appreciated.
Thanks
I assume your service accepts requests via HTTP ? Accept the request from your service and send back a HTTP 202 response. This response means that the request was accepted for processing. When you send the response, send the Location header to tell the client which URL to invoke to ascertain the status of your request. The client can poll this URL for status and a result.
The URL should contain a unique ID for each request. Your server can track that and populate a response when it is ready.