Navigating website with HtmlUnit after logging in with WebRequest - htmlunit

I had issues using HtmlUnit's click functionality to log in using the form, so I decided to log in using a WebRequest instead.
The way the site logs in is that the submit button for the form is an ajax call to a separate URL. Once the response from that POST request is received, the page reloads automatically and you are logged in.
// Client configuration
WebClient webClient = new WebClient(BrowserVersion.CHROME);
webClient.getOptions().setJavaScriptEnabled(true);
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getOptions().setCssEnabled(false);
webClient.setAjaxController(new NicelyResynchronizingAjaxController());
// Get cookies (Not sure if necessary to log in)
HtmlPage webPage = (HtmlPage)webClient.getPage("https://www.marinetraffic.com/");
URL cookieURL = new URL("https://www.marinetraffic.com/");
String cookies = webClient.getCookies(cookieURL).toString();
// Configure request headings
URL url = new URL("https://www.marinetraffic.com/en/users/ajax_login");
WebRequest requestSettings = new WebRequest(url, HttpMethod.POST);
requestSettings.setAdditionalHeader(":authority", "www.marinetraffic.com");
requestSettings.setAdditionalHeader(":method", "POST");
requestSettings.setAdditionalHeader(":path", "/en/users/ajax_login");
requestSettings.setAdditionalHeader(":scheme", "https");
requestSettings.setAdditionalHeader("accept", "*/*");
requestSettings.setAdditionalHeader("accept-encoding", "gzip,deflate,sdch");
requestSettings.setAdditionalHeader("accept-language", "en-US,en;q=0.8");
requestSettings.setAdditionalHeader("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
requestSettings.setAdditionalHeader("cookie", cookies);
requestSettings.setAdditionalHeader("origin", "https://www.marinetraffic.com");
requestSettings.setAdditionalHeader("referer", "https://www.marinetraffic.com/en/ais/home/centerx:-33.1/centery:21.4/zoom:4");
requestSettings.setAdditionalHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36");
requestSettings.setAdditionalHeader("x-requested-with", "XMLHttpRequest");
// Request body with form information
requestSettings.setRequestBody("_method=POST&email=dummy%40gmail.com&password=fakepassword&is_ajax=true");
// redirectPage is of type UnexpectedPage
Page redirectPage = webClient.getPage(requestSettings);
webClient.waitForBackgroundJavaScript(10 * 1000);
// Console confirms login was a success
System.out.println(redirectPage.getWebResponse().getContentAsString());
System.out.println(webClient.getCookies(cookieURL).toString());
// When I try to navigate to the main page I am not logged in
HtmlPage webPage2 = (HtmlPage)webClient.getPage("https://www.marinetraffic.com/");
System.out.println(webPage2.asXml());
I've also tried doing a WebRequest GET call with the updated cookies to the main site, but that also returned an UnexpectedPage. Now that I've logged in correctly, how would I go about getting an HtmlPage to navigate the website?

Just try to interact like a normal user with this page
get the page
locate the sign in element
click on the sign in element
locate the input fields
type your userid and password into the fiels
locate and click the sign in button
Maybe you have to add some wait code somewhere.

Related

Cypress Redirect To Incorrect (new url)

I'm trying to test the submission of a form. However, when I submit the form and wait/check for an element the form navigates to an new/incorrect domain. Example:
Form URL: https://formsenv.test.co.uk/IdentityDocuments/Submission/Index
Page it tries it navigate to: (new url) https://sts.test.co.uk/IdentityDocuments/default/Thankyou
It looks like it's taking the base url from the browser url field (screenshot - had to redact some info)
Screenshot of runner
Quick code snippet:
cy.get('[id="submitButton"]').click()
//Commented out as this didn't help...I tried to wait for the request to see //if I was requesting the 'cy.get('[id="thankyou-details-panel"]')' element //too early
//cy.intercept({
//method: 'GET',
//url: '/IdentityDocuments/default/Thankyou',
//}).as('dataGetFirst');
// Wait for response.status to be 200
//cy.wait('#dataGetFirst').its('response.statusCode').should('equal', 200)
cy.get('[id="thankyou-details-panel"]').should('contain','Thank you for completing the ID verification / Right to Study form. You will be notified if there are any issues with the document(s) provided.')
any help would be appreciated. Thanks

Phonegap Ajax request.responseText empty, trying to get a csv file from a yahoo stock info link

I'm developing an app using only html, javascript and css because I'm making it for phonegap (so no php or anything like that). I am trying to develop a simple stock quotes application that uses the yahoo stock csv api.
This api works by providing it the symbol of any given stock and it will download a csv file that gives you information about the stock.
An example would be if you look up info about Tesla Motors, its stock symbol is TSLA, and you would use the following link:
[http://download.finance.yahoo.com/d/quotes.csv?s=TSLA&f=nsl1op&e=.csv][1]
Going to this link manually, will automatically download the csv file with the info on Tesla Motors, so the file contents would look something like this:
"Tesla Motors, Inc","TSLA",84.35,81.23,83.24
But when I try to get it in my app, it returns an empty response. Here is how I try to get the info:
function getStockInfo(stockSymbol) {
var request = new XMLHttpRequest();
request.open("GET", "http://download.finance.yahoo.com/d/quotes.csv?s=" + stockSymbol + "&f=nsl1op&e=.csv", true);
request.send();
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200 || request.status == 0) {
alert("response: " + request.responseText);
var stockInfo = request.responseText.split(",");
localStorage.companyName = stockInfo[0];
localStorage.stockSymbol = stockInfo[1];
localStorage.startPrice = stockInfo[2];
localStorage.endPrice = stockInfo[3];
localStorage.highPrice = stockInfo[4];
document.location.href = "stockInfo.html";
}
}
}
}
The line that says alert("response: " + request.responseText); shows the request.responseText is blank. Am I doing this wrong? If it's a link that downloads a csv file, do you have to get the request differently? Is there a special way of doing this for phonegap?, I've been trying to find the answer on this, but haven't managed to. I would appreciate any help on this.
If you watch the console, you will see the following error :
XMLHttpRequest cannot load
http://download.finance.yahoo.com/d/quotes.csv?s=TSLA&f=nsl1op&e=.csv.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
You have to allow the access to the yahoo server. In config.xml add the line
<access origin="*" /> if you want to allow access to any server or
or <access origin=http://download.finance.yahoo.com" /> if you only want to allow access to the yahoo server
http://docs.phonegap.com/en/edge/guide_appdev_whitelist_index.md.html#Whitelist%20Guide

MVC unobtrusive AJAX, returning Json data, and IE

So there are lots of questions out there about this whole "IE opens a download file dialog for Json data returned via Ajax" (like this one or this one), but I have not found any answers for those who use Unobtrusive Ajax.
We do a simple Ajax.BeginForm like this:
Ajax.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl },
new AjaxOptions { UpdateTargetId = "ContentContainer", OnSuccess = "JsonCheckRedirect" },
new { id = "form1" }
)
This posts the form with Content Type of "application/x-www-form-urlencoded; charset=UTF-8". The Controller processes the form, and if there is an error, it returns a PartialView with Content Type "text/html", and that HTML gets put into the ContentContainer (because of the "UpdateTargetId" property in the AjaxOptions).
If there is no error, and the user logged in successfully, it returns Json with the URL they should be redirected to. So in the Controller, it's just simply this:
return Json(new { Url = returnUrl });
Except that we just had a user notify us that in IE8, this is causing the download dialog to pop up. After reading all these other questions with the same issue, I understand why this is happening, but the fix for those situations is to use this Json return instead:
return Json(new { Url = returnUrl }, "text/html");
The problem is that when I return like this, I guess Unobtrusive Ajax sees that the response from the server is HTML, and it replaces the content in the UpdateTargetId container. It does not do this when the server responds with "application/json".
Is there any way around this?
(do I need to explain anything further?)
If you return the url like that, you are going to need to override the Success handler and check the result to see if it has the Url property and then putting the result into window.location.
Personally, rather than returning a new Json result, I would send back a 302 which should make the ajax handler redirect you.
This happens in the bowels of jQuery if memory serves, so you don't need to change anything.
So rather than returning that json result on a successful login, try using a redirectToRoute result instead and send them to the page you want them to go to.

Spring - download file and redirect

I have a download link on my page which works just fine but it doesn't refresh/redirects my page. Here's my code.
#RequestMapping(method = RequestMethod.POST, params = "exportToXML")
public String exportToXML(HttpServletResponse response, Model model, #ModelAttribute(FILTER_FORM) ScreenModel form,
BindingResult result, OutputStream out,
HttpSession session) throws IOException {
ZipOutputStream zipout;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
zipout = new ZipOutputStream(baos);
ZipEntry ze = new ZipEntry("file.xml");
zipout.putNextEntry(ze);
zipout.write(string.getBytes());
zipout.closeEntry();
zipout.close();
baos.close();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition", "attachment; filename=xx.zip");
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().close();
response.getOutputStream().flush();
return VIEW_NAME;
}
I've removed irrelevant pieces of code to make it a little bit shorter. I have also tried with #ResponseBody but it gives the same result as code above.
Any advice will be helpful
You can't download file and make refresh/redirect.
I'll try to explain causes. Request flow is illustrated here:
where yellow circle is your controller. When you return view name front controller looks for appropriate view template (simply jsp, tiles or other, depending on configured view resolver) gets response and write generated html (or not html) code to it.
In your case you perform actions:
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().close();
response.getOutputStream().flush();
After that actions spring can't open response and write refreshed page to it (because you do it before).
So you can change your method signature to:
public void exportToXML(HttpServletResponse response, Model model, #ModelAttribute(FILTER_FORM) ScreenModel form,
BindingResult result, OutputStream out,
HttpSession session) throws IOException {
and delete last "return VIEW_NAME". Nothing will change.
You can:
response.setHeader("Refresh", "1; url = index");
This refresh the page after 1 second after response on URL: "index".
It will not. The browser opens the ms-excel contentType in a new window or you get a download prompt. The page that initiated download never get a chance to handle the redirect or page transition.
If the download + page refresh is desired, a JavaScript function could initiate the download and direct the user to next page, that page could say 'your download will commence shortly' or something similar.
You could after download, call a javascript function to submit to you controller and them show a different page.
I used the following structure to solve my problem. The function submit the form and back, in other words, you download the file and refresh the previous link. Using this solution, you can even show and hide messages errors with some template render, in my case, I used Thymeleaf.
To make the code more readable, I removed the Thymeleaf tags.
JS file:
function submitAndBack(formId) {
let formDoc = document.getElementById(formId);
formDoc.submit();
sleep(1000).then(function() {
window.history.back();
});
}
function sleep(milliseconds) {
return new Promise(function (resolve) {
setTimeout(resolve, milliseconds);
});
}
HTML form:
<form id="myForm" method="POST" action="/some/url">
<label for="inputText">Some info</label>
<input id="inputText" name="inputText" type="text">
<button onclick="submitAndBack('myForm')">
Submit
</button>
</form>
From LottaLava answer, I got the idea to solve a similar problem.
In JavaScript, after form submission, I wait for one and a half-second and then reload the page. The waiting time is to time for the backend to download the file (here exportToXML) and return the response and then in JavaScript refresh the page.
form.submit();
sleep(1500).then(function() {
document.location.reload();
});
Here form.submit() calls the controllers action, in your case exportToXML.
The sleep function is as follows:
function sleep(milliseconds) {
return new Promise(function (resolve) {
setTimeout(resolve, milliseconds);
});
}
The sleep function refers to here

Django - Start Session by Ajax Request

I need to know how to start a session by Ajax in Django. I'm doing exactly as described bellow, but it is not working! The request is sent correctly, but don't start any session. If a request directly without ajax it works! What is going on?
'# urls
r'^logout/$', 'autenticacao.views.logout_view'
'# view of login
def login_view(request):
username = request.GET.get('username', '')
password = request.GET.get('password', '')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse(user.get_profile().sos_user.name)
return HttpResponse('user invalido')
'# ajax in a html page
$(function(){
$.get('http://localhost:8000/logout/?username=usuario?>&password=senha', function(data){
alert(data);
});
You're not calling the login_view. You're ajax request is going to the /logout/ url which is calling the autenticacao.views.logout_view.
Also, The ?> after username=usuario doesn't look right in the your get url.
My guess is you should be doing something like http://localhost:8000/login/?username=usuario&password=senha. (but I'd need to see your login url mapping to be sure).
Also, you should be POSTing the login information and using HTTPS for security reasons, but that's a different issue.

Resources