HtmlUnit, how to check if every asset was loaded? - java

I am using HtmlUnit for integration-testing.
In HtmlUnit, there is WebResponse::getStatusCode() for accessing HTTP_STATUS_CODE of currently loaded page. Let's say, my Page is "about" google.com, statusCode will be 200, usually.
I am wondering, if it is possible with HtmlUnit to check, if all required assets (*.css, *.js) were loaded successfully (200 <= statusCode < [300|400]).
In my use case, my tested page works fine - but a .css-file is missing, so the layout is broken. I would like to assert in my test-case, that each required assert can be loaded.

You can intercept all communication and store information about all assets.
Something like:
new WebConnectionWrapper(webClient) {
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response = super.getResponse(request);
URL url = request.getUrl();
int status = response.getStatusCode();
// store the status
return response;
}
};

Related

How to create a POST request for a file upload

I am currently uploading some files via the API from Opentext Content Server 21.2. I have already implemented most of the method calls. I can upload files, create folders, delete files and so on. However, I am currently failing with the file upload. Mainly only PDFs or images (Jpeg, PNG etc.) should be uploaded.
The current API documentation can be found here:
https://developer.opentext.com/apis/14ba85a7-4693-48d3-8c93-9214c663edd2/d7540c64-7da2-4554-9966-069c56a9341d/a35ce271-5bb7-4bcf-b672-0c8bcf747091#operation/createNode2
My current code looks like this:
#Override
public ClientResponse saveFile(String sessionId, String folderId, File document, String filename) throws DmsException, IOException {
client = ClientHelper.createClient();
client.addFilter(new LoggingFilter());
Builder webResource = client.resource(getRestUri() + REST_CREATE).header("otcsticket", sessionId);
MultivaluedMap<String, String> postBody = new MultivaluedMapImpl();
postBody.add("name", filename);
postBody.add("type", TYPE_FILE);
postBody.add("parent_id", folderId);
postBody.add("file", FileUtils.readFileToString(document, StandardCharsets.UTF_8));
ClientResponse response = webResource.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).post(ClientResponse.class, postBody);
if (response.getStatus() == 200) {
return response;
} else {
System.out.println(response.toString());
System.out.println(response.getEntity(String.class));
throw new DmsException("XYZ-001", XYZ: HTTP-CODE "
+ response.getStatusInfo().getStatusCode() + " - " + response.getStatusInfo().getReasonPhrase());
}
}
The code returns a HTTP-STATUS 200 OK. However, no file is created, but a folder is created. The API description for this is identical only with the difference that no file is passed. Therefore I assume that the file parameter is skipped.
PS: I am using Jersey 1.19.1
I ask for help and am grateful for any answer

Is it possible to indicate that the web session will be valid for a single site (or page)?

Let me explain myself well. I'm integrating my application with Jasper Report Server and I'm preventing the username and password from being sent via URL (with GET) to view a report.
For that I'm using a rest_v2 service for autenticate the user with a POST request and using the response body with the JSESSION to redirect the request to the Jasper Report (this time the site will not redirect to the login site because I got a valid session token).
What I want to do is limit the sites in which that session will be available, I only want it to be valid for the report page and that if the user tries to access the repository, then the session will not be available and the webpage redirects to the jasper login screen
Example: User request for a report which can be accesed in the url
/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FReports&reportUnit=%2FTest%2FJasper_Report
If the user tries to go here outside of this URL, then the session will not be valid anymore.
Here is my source
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpPost post = new HttpPost("http://localhost:8080/jasperserver/rest_v2/login");
int coderes;
String username = request.getParameter("username");
String pass = request.getParameter("pass");
List<NameValuePair> urlParameters = new ArrayList<>();
urlParameters.add(new BasicNameValuePair("j_username",username));
urlParameters.add(new BasicNameValuePair("j_password",pass));
post.setHeader("type", "POST");
post.setHeader("cors", "true");
post.setHeader("contentType", "application/x-www-form-urlencoded");
post.setHeader("secure","true");
post.setEntity(new UrlEncodedFormEntity(urlParameters));
Header[] headers = null;
try(CloseableHttpClient client = HttpClients.createDefault();
CloseableHttpResponse chres = client.execute(post)){
StatusLine status = chres.getStatusLine();
coderes = status.getStatusCode();
headers = chres.getAllHeaders();
}
if(coderes == 200) {
for(int i = 0; i < headers.length; i++) {
if(headers[i].getName().equals("Set-Cookie")) {
response.addHeader(headers[i].getName(), ServletUtils.setCookieValue(headers[i].getValue().split(";"), "/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FPublished&reportUnit=%2FPublished%2FUser_Report&standAlone=true"));
} else {
response.addHeader(headers[i].getName(), headers[i].getValue());
}
}
response.sendRedirect("http://localhost:8080/jasperserver/flow.html?_flowId=viewReportFlow&_flowId=viewReportFlow&ParentFolderUri=%2FPublished&reportUnit=%2FPublished%2FUser_Report&standAlone=true");
} else {
response.getWriter().println("Incorrect Credentials");
}
}
The setCookieValue method
public static String setCookieValue(String[] attr, String requestUrl) {
Date targetTime = Calendar.getInstance().getTime();
SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
targetTime = DateUtils.addMinutes(targetTime, 5);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < attr.length; i++){
if(attr[i].contains("userLocale")){
attr[i] = "userLocale=es_ES";
}else if(attr[i].contains("Expires")) {
attr[i] = "Expires=" + fmt.format(targetTime) + " GMT";
}else if(attr[i].contains("Path")){
attr[i] = requestUrl;
}
sb.append(attr[i]).append(";");
}
return sb.toString();
}
In this method what I try to do is to put the requested URL in the attribute Path, because what I understood from this site:
This method gets the path to which this cookie applies.
Maybe I'm typing the URL wrong or I'm using the wrong attribute.
I feel that it's possible
Theoretically you can manipulate the cookie of the Java HTTP session (it works at least for Tomcat and Spring Boot). Setting the session cookie Tomcat makes it accessible over the HttpServletResponse instance. You can overwrite JSESSION cookie replacing the Path attribute.
But such a manual manipulation is not covered by JEE standard and it will be really painful to debug this solution.
I have a better idea! Is Jasper Report Server embedded in your application as a third party servlet? If yes, I would suggest to wrap a custom filter around this Servlet. The filter can be specified in "web.xml". Inside the filter you need to create a proxy for HttpServletRequest and inject any authentication information you want. You can emulate anything on this level including a fake HTTP session.
What I had in mind was too difficult to achieve, so instead I decide to create a new role with the "only execute" permission to re-create this "effect".
If the user tries to navigate through the report repository, the folders will not loaded.

Problem with RestTemplate when including URL addresses in REST API request

I'm trying to obtain data from Botify's REST API to use it inside a project, which is also a REST API. I'm using an instance of Spring's RestTemplate class to make the actual requests to Botify, specifically the .exchange method as I need to pass Botify's key as a header parameter.
My problem comes when I need to call to a method of the endpoint which takes a URL as a part of the request's URI (not a parameter). Documentation of this endpoint is in https://developers.botify.com/api/reference/#!/Analysis/getUrlDetail
Basically the structure of the requests is like this:
/analyses/{username}/{project_slug}/{analysis_slug}/urls/{url}
The last part of that URI is a URL address, which needs to be encoded in UTF-8 to make it possible to separate it from the actual request.
The problem is (I believe) that the .exchange method always encodes the request, so what I try to send like this:
/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com
...ends up like this:
/analyses/myusername/myprojectname/myprojectslug/urls/https%253A%252F%252Fwww.example.com'
Which obviously doesn't work. This is an excerpt from the method that makes the call to Botify:
public String callBotifyEndpoint(String reportType, String parameters) throws UnsupportedEncodingException {
String request = this.baseUri + "/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com"
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Token " + this.apiKey);
HttpEntity<String> entity = new HttpEntity<>(headers);
UriComponentsBuilder botifyQueryBuilder = UriComponentsBuilder.fromUriString(request);
String queryStringBuild = botifyQueryBuilder.build(true).toUriString();
String botifyResult = null;
try {
System.out.println("Calling Botify API: " + queryStringBuild);
ResponseEntity<String> response = botifyTemplate.exchange(queryStringBuild, HttpMethod.GET, entity, String.class);
if(response.hasBody()) {
botifyResult = response.getBody();
}
} catch(RestClientException ex) {
ex.printStackTrace();
}
try {
} catch (Exception e) {
// TODO: handle exception
}
return botifyResult;
}
In this line:
botifyQueryBuilder.build(true).toUriString();
The "true" parameter indicates whether the data is already encoded or not. I've tried to disable it but the result is the same.
I've removed actual request generation process (along with my user and project's name) to simplify things, but this should return a response from Botify with the existing data for that URL.
Instead, it returns a 400 bad request error (which makes sense, because the URL is not correct).
I'm feeling like this may be a bug in RestTemplate's .exchange method, but maybe I'm not using it properly. Any suggestions?
Don't encode prematurly as you do here:
String request = this.baseUri + "/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com";
Use parameter placeholders feature in RestTemplate instead of text concatenation.
Refer to:
Spring RestTemplate GET with parameters

com.google.gwt.user.client.Window How to get Http status code from answer?

I use com.google.gwt.user.client.Window.open(String url, String name, String features) to download file from server.
Every think is ok when the result from server is 200 OK- I am getting file.
Problem comes when the result from server is different than 200 OK, for example: 500 Internal Server Error, or 401 Unauthorised. Then I am getting ugly Tomcat Error page that contain information about the problem.
I would like to catch every status code different than 200 OK and display my own information or redirect to f.e. Login Page.
How can I achive this?
To achieve required functionality, first we need to check for existence of file on server. We can do that by simple head request. Here is a sample code for same
XMLHttpRequest req = XMLHttpRequest.create();
req.open("HEAD", fileURL);
req.setOnReadyStateChange(new ReadyStateChangeHandler() {
#Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == XMLHttpRequest.DONE) {
if (xhr.getStatus() == 200) {
Window.open(fileURL, winTitle, "");
} else {
// TODO handle other status codes
}
}
}
});
req.send();

Checking the status of a web page [duplicate]

This question already has answers here:
How to use java.net.URLConnection to fire and handle HTTP requests
(12 answers)
Closed 9 years ago.
Need to make a program that takes a valid URL of a webpage like www.stackoverflow.com/questions and its IP address equivalent. The program will then find that webpage and return the status code of the page to us such as 200 OK and 404 NOT FOUND. If the webpage isn’t reachable, a message should be returned explaining the situation.
Here’s what I have done so far:
interface Result {
public boolean ok ();
public String message (); }
class Page {
public Result check ( String wholeURL ) throws Exception {
throw new Exception ( "Not sure about the rest”); } }
Also if I were to check a page like http://www.stackoverflow.com I’ll create an instance of Page and then do something like this:
Page page = new PageImplementation ();
Result result = page.check ( "http://www.stackoverflow.com:60" );
if ( result.ok () ) { ... }
else { ... }
The object that is returned is an instance of Result, and the “ok” method should return true when the status code is 200 OK but false otherwise. The method “msg” should return the status code as string.
Have a look at the HttpURLConnection class within the JDK or use Apache Http Components.
Basically you try to connect to the url and check the response header or wait for a timeout if the server isn't reachable at all.
With HttpURLConnection it might look like this:
URL url = new URL("http://www.stackoverflow.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.connect();
int httpStatusCode = connection.getResponseCode(); //200, 404 etc.
You can use some api like commons http ,
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
..........
public Result check ( String fullURL ) throws Exception {
HttpClient client = new HttpClient();
GetMethod method = new GetMethod(url);
int statusCode = client.executeMethod(method);
//Update your result object based on statuscode
}

Categories

Resources