im building a little web app that uses jetty 8 as server and websockets.
On client (browser) side: the user opens with his browser my index.html and that opens and establishes a new WebSocket connection with my jetty server.
On server side, i have a WebSocketServlet that listens on incomming WebSocket connection.
#Override
public WebSocket doWebSocketConnect(HttpServletRequest request, String arg1) {
System.out.println("doWebSocketConnect");
System.out.println("WebSocket "+request.getSession().getId());
return new UserWebSocket(request.getSession());
}
UserWebSocket is a class that implements jetty's WebSocket.OnTextMessage interface for receiving and sending messages via websockets.
So far so good, everything works fine so far.
So what i now want to do, is to work with HttpSession to identify the current user, because
the index.html site can also do some ajax calls on other (non WebSocket) Servlets, like submit some simple form data via HTTP POST etc.
For example have a look at my SearchServlet:
public class SearchServlet extends HttpServlet{
...
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(request.getSession());
}
...
}
My problem is, that this two servlets (WebSocketServlet and SearchServlet) have two diffrent HttpSession object with two diffrent HttpSession ids:
for exmaple my WebSocketServlet have got the session id = 1dwp0u93ght5w1bcr12cl2l8gp on doWebSocketConnect() and the SearchServlet got the session id = 1sbglzngkivtf738w81a957pp, but the user is still in the same browser and on the same page (index.html) and have not reloaded the page etc. The time between establishing a WebSocket connection and the SearchServlet call is just a few seconds ...
Any suggestions?
EDIT: btw.
Both Servlets are in the same ServletContext:
ServletContextHandler servletContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContext.setContextPath("/servlets");
servletContext.addServlet(new ServletHolder( new MyWebSocketServlet()),"/liveCommunication");
servletContext.addServlet(new ServletHolder( new SearchServlet()),"/search");
There are two possible causes that I can see.
1 - Your server is not correctly configured. Since you haven't provided the details about how you're running Jetty, and how you've configured it, it's certainly possible that you've introduced a problem there.
2 - It's actually a timing issue.
I assume your index.html is static content, so it doesn't create a session on its own.
Within the index.html there is some javascript that will launch two separate requests. One as a WebSocket, the other as an XMLHttpRequest (AJAX). Since the 2 requests are launched simultaneously, they have the same set of cookies - which in this case is none.
In each case, since the request provides no cookies, the server must generate a new HTTP Session. There server does not know that the two requests are from the same client, so 2 separate HTTP sessions are created.
If that's the case, then you could fix it quite simply by putting a filter in front of the index.html, that forces the creation of the session.
Related
I am trying to call a SOAP RPC style web service and getting the following error:
Exception in thread "main" com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 302:
This is a https web service and I have imported the certificate into cacerts thru browser but getting same result. Please note that, I can consume a REST webservice from the same machine without importing the certificate.
What I am missing when calling a SOAP service? Is it my client issue or something need to be done on the server side. I have access to the server.
HTTP status code 302 is a redirect, and so is unlikely due to a certificate problem. My initial guess is that you need to add a / (or remove it) from your URL. Some http server frameworks will redirect when a resource does not end in a /, so, instead of:
GET /myRpcEndpoint
Try
GET /myRpcEndpoint/
The other possibility is that this resource requires authentication and the server is redirecting you to a login page. If you want to know what is going on (and not guess), take a look a the the response headers for the 302. There will be a Location header telling you where the server wants you to go instead.
Had a similar issue where client code would receive a HTTP 302 error code when communicating with https and would work fine when communicating with http. In client code,you might need to specify the endpoint address on the request context using the BindingProvider.ENDPOINT_ADDRESS_PROPERTY property. Following the JAX-WS paradigm, the example below should work.
Please note that only the BindingProvider.ENDPOINT_ADDRESS_PROPERTY needs to be defined, the rest of your code should remain the same.
public static void main(String args[]) throws {
ObjectFactory factory = new ObjectFactory();
GetProducts_Service service = new GetProducts_Service();
GetProducts getProducts = service.getGetProductsPort();
final BindingProvider getProductsBP = (BindingProvider) getProducts;
getProductsBP.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
"https://example.server.net/ExampleServicesWar/GetProducts");
GetProductsRequest request = factory.createGetProductsRequest();
GetProductsResponse response=getProducts.getProducts(request);
List<Product> products=response.getProducts();
}
All you have to is to use correct end point url
((BindingProvider)port).getRequestContext().put(BindingProvider.
ENDPOINT_ADDRESS_PROPERTY, "https://yourservice");
Need to import at the top:
import javax.xml.ws.BindingProvider;
port is Method call:
full source:
private static String getApplicationStatus(java.lang.String remoteAccessKey, java.lang.Integer responseId) {
net.quotit.oes._2010.ws.applicationstatusupdate.OASStatusUpdateService service = new net.quotit.oes._2010.ws.applicationstatusupdate.OASStatusUpdateService();
net.quotit.oes._2010.ws.applicationstatusupdate.IApplicationStatusUpdate port = service.getStatusUpdate();
((BindingProvider)port).getRequestContext().put(BindingProvider.
ENDPOINT_ADDRESS_PROPERTY, "https://servicename/basic");
return port.getApplicationStatus(remoteAccessKey, responseId);
}
I have created an HttpClient in C#
Client = new HttpClient(handler);
The handler is this
var handler = new HttpClientHandler
{
CookieContainer = CookieContainer,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
I send some requests in a site, let's say it is xyzevents.com. I receive my responses normally, I store some cookies I receive from "Set Cookie:*" commands, everything works good.
However, after this I try to communicate with the site xyz.com. In order to do that, I must send my requests, using the cookies I stored from xyzevents.com earlier. The HttpClient can't do that, because it sees the host is different than xyzevents.com.
Is there a way to bypass that check, and send my requests with no problem?
I don't think there's anyway to "disable" this check. I think it's the HttpClient that ends up deciding which cookies should be sent, not the container. And in the end, the security risks that could happen by sending random cookies anywhere are pretty large.
With that, you could easily loop through all the cookies received from xyz.com, create them manually with the domain changed but the same values. Then add them to a new collection which is sent to xyzevents.com.
I am badly stuck with a SOAP based integration using Axis2 framework for generation of client stubs from the Server WSDL. The scenario is as follows :
There is always a login API call first, which gives a Success response in SOAP body and Temporary Redirect in HTTP header. Also provides a URL which contains the session ID in the Location field of HTTP Header.
The next API call is required to be made at this redirect location. IN THE SAME TCP CONNECTION, for getting a proper response.
Now, the problem is, as a part of Webservice implementation using Axis2 generated stubs, I need to reload this redirect URL and re-instantiate it as --- "stub=new Stub(newurl)"
As soon as this is done, it creates a new TCP connection and so, the next request gives the response as "session ID invalid" because it goes out-of-sync with login API.
I have tried everything mentioned as a solution in this forum and nothing is working out.
For e.g --
MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
HttpClient httpClient = new HttpClient(httpConnectionManager);
ServiceClient serviceClient = stub._getServiceClient();
Options opts = stub._getServiceClient().getOptions();
opts.setTo(new EndpointReference(prop.getProperty("target_end_point_url")));
opts.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
opts.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
serviceClient.setOptions(opts);
stub._setServiceClient(serviceClient);
Similarly, I have tried many other options too. But it's not helpful at all.
Faced exactly the same issue.
Following steps solved the issue.
1. Using HttpClient, perform login. Don't use stub object to perform login.
2. Use the Location Header URL, to create new stub object i.e. stub = new Stub(locationURL). (Your existing options setting should be retained.)
3. There is a default timeout, by which server disconnects the TCP connection. In my case it was 50 seconds. Hence as soon as i performed login in step 1, i execute a timer every 40 seconds, to send an empty requests to new Location URL using HeadMethod of same HttpClient object.
I have the following NancyFX unit test.
var browser = new Browser(new UnitTestBootstrapper());
var response = browser.Post("/login", with =>
{
with.FormValue("UserName", userName);
with.FormValue("Password", password);
});
response.ShouldHaveRedirectedTo("/home");
You can see that I use an instance of Nancy.Testing.Browser to POST some form values. I would like to capture this Http request in Fiddler but I am not sure how to set-up the Browser (a proxy perhaps?)
Thanks
You can't because they never hit the network; that's the whole point of the browser class - to give you end to end testing without the performance hit/configuration issues of having to use hosting/http/networking/browser rendering.
If you want to go via the networking stack then use something like Selenium, or spin up a self host and poke it with EasyHttp or manually with HttpClient.
I am trying to understand what things happen in the background when using a website OR basically what are the things that happen when a user interacts with a browser. I understand that this is a huge list and highly dependent on architecture and user actions etc, I am just trying to get a feel of major things and flush my misunderstandings and also use this to read more about stuff I don't understand.
As an exercise I am trying to note down things that happen in the background with respect to users action in a browser. Here is my attempt at this bit open ended but fun question:
User enters a url => browser checks if
available in browser cache => DNS look
up [root dns lookup => recursive dns
=> get ip ] => establish a tcp connection => send http req => get
the static page from web server=> if
authentication is required that
happens [either read cookies from
browser OR ask user to enter
credentials] => somehow gets the
dynamic elements as well [how ? ,
there is some lazy initilization here
?] => Then user performs some
action[clicks a link or something] =>
check browser cache => if not avail
[take the input parameters and embed
in the url in some manner [may be
encrypt some things if required] =>
hits a load balancer => directed to a
application server [depending on how
the LB selects a host] => application
server cache is checked [memcached or
some kind of caching, not sure if this
"normally" happens here or at some
other level] => application server
tries to understand the request [if
its a service listening on some port,
http port 80 it will get the URL and
parse to perform some operations] =>
database is queried if required to =>
there might again be connection
mgmt/caching/parallel queries etc here
=> database returns back the result to app server => app server creats a
result payload and headers [http] =>
sends it to browser for rendering =>
browser cache is updated => user
reacts to the response.
I have not considered retries/failures and how they are handled, but I would like to get some input there as well in a general sense
Note:
I am looking at things in general, I am sure that few companies might do it in different way etc etc. I will like to hear alternatives as well though!.
This is an effort to try and get more
perspective and read on few things
that will help me in general.
Clearly I have made an honest attempt
I also hope this would help others
looking at the question in general to
learn something new.
I am not asking
for opinions etc, so this aint a
completely open ended question [not
everything is right though there are
many options]
Thanks !
There is no difference between static or dynamic for browser. Browser makes HTTP request and gets HTTP response. If response is an HTML page, then browser renders HTML ,applies styles, and executes JavaScript code that come with page. This page can by dynamic or static - browser don't care! The side is care - is server side. If page is static, than HTTP server will just take page from disk and send it to client as HTTP response. If page is dynamic, than HTTP server will call some application and will ask this application to give requested resource. This application can be an PHP module for Apache(http server), or ASP.net for IIS, or even your C++ code that will generate any content you want.
How exactly page or resource (HTTP response can be also xml, or image etc) will be constructed depends on used application (server side technology).
As example, if you are using PHP - HTTP server will detect that requested resource has extension .php, server will pass this PHP file to PHP module for processing, and result will be sent to HTTP client(browser) as response.
When user perform some action, this is again just usual HTTP request. HTTP method GET and POST (look for article about HTTP on Wikipedia) is used to pass some input from server to client. Page can contain some heavy JS, that will make page look more like desktop application (rich controls, dynamically reacting on user action without request to server, or communicate with server in background), but this is not necessary for web application to be web application (for web site to by dynamic). It can be good old static HTML with HTML forms, and some server side code.
Web application is abstract entity that may consist from many HTTP resources (different URLs for server to response). Web application also is client-side code that communicates with server-side code thru HTTP with help of HTTP client(browser) and HTTP server. Web application is not some stand alone part, that only comes to work when user perform some action.
Web-service may fits this description - as thing that usually don't care about pages, and comes only when some action required. Its special type of web application, that expose some API thru HTTP(usually). You can request some resource, and pass some parameter, and you will get response with some result. It's same web application but without pages. But web-service usually part of big web application with pages, or even other part of same web-application (depending on how you look at this). It can be same server-side technology, and same HTTP server. And it's not necessary to create web-service if you want to make some web-application (dynamic web site).
Server-side part of web application can also communicate with some database, but it's not necessary too.
There can be real database, or just some text files on disk. And browser, client side code and HTTP server also don't care about database or source where server side code takes data.
Cache, load balancer, etc - it's just additional elements that usually are transparent for all this general stuff.
Cookies is passed with every HTTP request to HTTP server, and if requested resource is not static page, that HTTP server will pass them further to server-side code/application(part). And its usually how authentication and authorization works - cookies has contain info about session, and there is some data associated with session contains on server side - it can be ID of user, so server-side code will recognize user on every request.