How to add RequestInterceptor and change Referer in BrowserMob-Proxy 2.0 - selenium

I am using BrowserMob-Proxy inside a Selenium test suite. I would like to change the Referer for a few tests. I have added requestInterceptor from the 2.0 docs into our MyProxy class and while it does not generate an error the Referer is not changed.
For now, I am trying to get the requestInterceptor to work in the MyProxy class where the proxy is created. In the end, I would like to be able to specify the Referer in each test.
If anyone has suggestions on getting the requestInterceptor to work please let me know. Here is the MyProxy class. Please let me know if other code examples would be helpful to troubleshoot this.
import org.openqa.selenium.Proxy;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.proxy.ProxyServer;
import net.lightbody.bmp.proxy.http.BrowserMobHttpRequest;
import net.lightbody.bmp.proxy.http.RequestInterceptor;
public class MyProxy {
private ProxyServer proxy;
private boolean initialized;
public Har endCapture() throws Exception {
Thread.sleep(15000);
return this.proxy.getHar();
}
public Proxy getSeleniumProxy() {
return this.proxy.seleniumProxy();
}
public boolean isInitialized() throws Exception {
return this.initialized;
}
public void start() throws Exception {
int proxyPort = Integer.parseInt(System.getProperty("proxyPort"));
this.proxy = new ProxyServer(proxyPort);
this.proxy.start();
this.proxy.setCaptureHeaders(true);
this.proxy.setCaptureContent(true);
this.proxy.addRequestInterceptor(new RequestInterceptor() {
#Override
public void process(BrowserMobHttpRequest request, Har har) {
request.getMethod().removeHeaders("Referer");
request.getMethod().addHeader("Referer", "http://www.google.com");
}
});
this.initialized = true;
}
public void startCapture() throws Exception{
this.proxy.newHar("MyHar");
}
public void stop() throws Exception {
this.proxy.stop();
this.initialized = false;
}
}

I think the key here is how to test the newly-added header, which is tricky to do manually.
I chose as a test-site: http://headers.cloxy.net/request.php, which simply logs the names and values of all request headers. Having first set up my proxy, I arranged a screenshot to be written after page request completed.
I was able to determine that:
#Override
public void process(BrowserMobHttpRequest req, Har har) {
req.getMethod().removeHeaders("Referer");
req.getMethod().addHeader("Referer", "http://www.google.xyz");
// Some extras
req.getMethod().addHeader("Foo_" + System.currentTimeMillis(), "Bar_" + new java.util.Date());
req.getMethod().setHeader("Lorem_" + System.currentTimeMillis(), "Ipsum_" + new java.util.Date());
}
... successfully adds all the specified headers in both BrowserMob 2.0.0 and 2.1 beta 5. I've confirmed this for each version in Firefox (45), Chrome (49), and PhantomJS.
So, in short:
The OP's header-adding syntax is perfectly fine.
setHeader also works as expected.
BMP version numbers do not affect this (but by all means upgrade to 2.1 as/when it is released)
Browsers do not affect this

Review this issue and see if it describes your problem.
Suggestion is to move to the latest version of BrowserMobProxy which is 2.1.0-beta-5.

Related

Is it possible to add completion items to a Microsoft Language Server in runtime?

I am trying to develop a IntelliJ plugin which provides a Language Server with help of lsp4intellij by ballerina.
Thing is, i've got a special condition: The list of completion items should be editable in runtime.
But I've not found any way to communicate new completionItems to the LanguageServer process once its running.
My current idea is to add an action to the plugin which builds a new jar and then restarts the server with the new jar, using the Java Compiler API.
The problem with that is, i need to get the source code from the plugin project including the gradle dependencies accessable from the running plugin... any ideas?
If your requirement is to modify the completion items (coming from the language server) before displaying them in the IntelliJ UI, you can do that by implementing the LSP4IntelliJ's
LSPExtensionManager in your plugin.
Currently, we do not have proper documentation for the LSP4IntelliJ's extension points but you can refer to our Ballerina IntelliJ plugin as a reference implementation, where it has implemented Ballerina LSP Extension manager to override/modify completion items at the client runtime in here.
For those who might stumble upon this - it is indeed possible to change the amount of CompletionItems the LanguageServer can provide during runtime.
I simply edited the TextDocumentService.java (the library I used is LSP4J).
It works like this:
The main function of the LanguageServer needs to be started with an additional argument, which is the path to the config file in which you define the CompletionItems.
Being called from LSP4IntelliJ it would look like this:
String[] command = new String[]{"java", "-jar",
"path\\to\\LangServer.jar", "path\\to\\config.json"};
IntellijLanguageClient.addServerDefinition(new RawCommandServerDefinition("md,java", command));
The path String will then be passed through to the Constructor of your CustomTextDocumentServer.java, which will parse the config.json in a new Timer thread.
An Example:
public class CustomTextDocumentService implements TextDocumentService {
private List<CompletionItem> providedItems;
private String pathToConfig;
public CustomTextDocumentService(String pathToConfig) {
this.pathToConfig = pathToConfig;
Timer timer = new Timer();
timer.schedule(new ReloadCompletionItemsTask(), 0, 10000);
loadCompletionItems();
}
#Override
public CompletableFuture<Either<List<CompletionItem>, CompletionList>> completion(CompletionParams completionParams) {
return CompletableFuture.supplyAsync(() -> {
List<CompletionItem> completionItems;
completionItems = this.providedItems;
// Return the list of completion items.
return Either.forLeft(completionItems);
});
}
#Override
public void didOpen(DidOpenTextDocumentParams didOpenTextDocumentParams) {
}
#Override
public void didChange(DidChangeTextDocumentParams didChangeTextDocumentParams) {
}
#Override
public void didClose(DidCloseTextDocumentParams didCloseTextDocumentParams) {
}
#Override
public void didSave(DidSaveTextDocumentParams didSaveTextDocumentParams) {
}
private void loadCompletionItems() {
providedItems = new ArrayList<>();
CustomParser = new CustomParser(pathToConfig);
ArrayList<String> variables = customParser.getTheParsedItems();
for(String variable : variables) {
String itemTxt = "$" + variable + "$";
CompletionItem completionItem = new CompletionItem();
completionItem.setInsertText(itemTxt);
completionItem.setLabel(itemTxt);
completionItem.setKind(CompletionItemKind.Snippet);
completionItem.setDetail("CompletionItem");
providedItems.add(completionItem);
}
}
class ReloadCompletionItemsTask extends TimerTask {
#Override
public void run() {
loadCompletionItems();
}
}
}

JAX-RS Response.getEntity() always null

I need help with Arquillian test.
Add code example of situation.
This code is working ok in real environment. Only in test case made with arquillian the result is not expected
The code:
#Stateless
public class CustomerResourceImpl implements CustomerResource{
#Override
public Response findOne(String id) {
String res = "Un cliente";
return Response.ok(res).build();
}
}
#Path("customer")
#Produces(MediaType.APPLICATION_JSON)
public interface CustomerResource {
#GET
#Path("/findOne")
public javax.ws.rs.core.Response findOne(#QueryParam("id") String id);
}
And this test case
#RunWith(Arquillian.class)
public class CustomerResourceTest {
#Deployment (testable = false)
public static Archive createTestArchive() {
return ShrinkWrap
..... (mas)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
#ArquillianResource
private URL deploymentURL;
#Test
#RunAsClient
public void findOne(#ArquillianResteasyResource CustomerResource resource) throws Exception {
final Response response = resource.findOne("1");
System.out.println(response.getEntity()); // IS NULL ??
System.out.println(response.getStatus()); // 200 OK
assertNotNull(response);
}
}
The problem is that response.getEntity() is always NULL . Why? The status response OK = 200 , it is OK. This service run ok in jboss 7.2 with Java 8.
Thanks!
The reason is #Deployment (testable = false)
#Deployment says:
testable = Defines if this deployment should be wrapped up based on the protocol so the testcase can be executed incontainer.
So false means it will not be deployed in the container, and therefore will be null when your tests run inside the container.
I recommend using #Deployment with not parameters passed in rather than setting testable = true
I just solved this today after a days of fiddling. I think I pasted the #Deployment (testable = false) code from examples on the internet that I didn't understand hoping to get something working.

Create screenshot - Allure, JUnit5, Selenium

Is there any documentation about this? JUnit4 has #Rule and solution is straightforward. For JUnit5 I made a extension public class TestWatcher implements AfterTestExecutionCallback but I don't know what to put in #Override method.
I've managed to solve it. Method for screen capture is default one:
#Attachment(value = "{testName} - screenshot", type = "image/png")
private byte[] makeScreenshotOnFailure(String testName) {
return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
}
and TestWatcher (extension):
#Override
public void afterTestExecution(ExtensionContext extensionContext) throws Exception {
Object test = extensionContext.getRequiredTestInstance();
Field a = test.getClass().getDeclaredField("driver");
a.setAccessible(true);
driver = (WebDriver) a.get(test);
Method method = extensionContext.getRequiredTestMethod();
if (extensionContext.getExecutionException().isPresent()) {
makeScreenshotOnFailure(method.getName());
}
}
You can find a sample here. Is it a code from NoraUi Open Source Framework (Java + Selenium).
import org.openqa.selenium.TakesScreenshot;
final byte[] screenshot = ((TakesScreenshot) Context.getDriver()).getScreenshotAs(OutputType.BYTES);

Customize login in Grails Spring Security plugin

I have an application where the login should include an organization number, so the login needs to be username + password + organization number.
Sample case: If the username + password matches with an existing user, I need to check if that user has the organization id. If not, the login should fail.
I saw that the login form from spring security plugin submits to /app/j_spring_security_check but couldn't find where that is actually implemented.
Also I'm not sure if touching that is the right way of implementing this custom login.
My question is where / how to customize the login action? (to make it fail on the case I described above).
We can do this by overriding the filter UserNamePasswordAuthenticationFilter and provide our custom attemptAuthentication.
So, go to DefaultSecurityConfig.groovy file (inside plugins). See tree diagram below:
target
|-work
|-plugins
|-spring-security-core-2.0-RC5
|-conf
|-DefaultSecurityConfig.groovy
In DefaultSecurityConfig.groovy under apf closure we specify filterProcessUrl which we can override in grails application's Config.groovy like we do for other properties (e.g. rejectIfNoRule)
grails.plugin.springsecurity.apf.filterProcessesUrl="your url"
Now we understood how it checks for authentication.Let's customise it own way by overriding the method attemptAuthentication of filter named UsernamePasswordAuthenticationFilter. For example, see below(also, go through the inline comments added there)
package org.springframework.security.web.authentication;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.util.Assert;
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
/** #deprecated */
#Deprecated
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = "j_username";
private String passwordParameter = "j_password";
private String organisationParameter = 'j_organisation'
private boolean postOnly = true;
public UsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if(this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
String password = this.obtainPassword(request);
String password = this.obtainOrganisation(request);
//regular implementation in spring security plugin /**
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
**/
//Your custom implementation goes here(Authenticate on the basis of organisation as well). Here you need to customise authenticate as per your requirement so that it checks for organisation as well.
}
protected String obtainOrganisation(HttpServletRequest request) {
return request.getParameter(this.organisationParameter);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(this.passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(this.usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return this.usernameParameter;
}
public final String getPasswordParameter() {
return this.passwordParameter;
}
}
Hence, it's more of a overriding task in terms of spring security.
To get more clearer idea about same read this nice link for java
and
for grails read this
Hope it helps.
These blogs gives a more detailed idea of the same requirements.

How to implement a Restlet JAX-RS handler which is a thin proxy to a RESTful API, possibly implemented in the same java process?

We have two RESTful APIs - one is internal and another one is public, the two being implemented by different jars. The public API sort of wraps the internal one, performing the following steps:
Do some work
Call internal API
Do some work
Return the response to the user
It may happen (though not necessarily) that the two jars run in the same Java process.
We are using Restlet with the JAX-RS extension.
Here is an example of a simple public API implementation, which just forwards to the internal API:
#PUT
#Path("abc")
public MyResult method1(#Context UriInfo uriInfo, InputStream body) throws Exception {
String url = uriInfo.getAbsolutePath().toString().replace("/api/", "/internalapi/");
RestletClientResponse<MyResult> reply = WebClient.put(url, body, MyResult.class);
RestletUtils.addResponseHeaders(reply.responseHeaders);
return reply.returnObject;
}
Where WebClient.put is:
public class WebClient {
public static <T> RestletClientResponse<T> put(String url, Object body, Class<T> returnType) throws Exception {
Response restletResponse = Response.getCurrent();
ClientResource resource = new ClientResource(url);
Representation reply = null;
try {
Client timeoutClient = new Client(Protocol.HTTP);
timeoutClient.setConnectTimeout(30000);
resource.setNext(timeoutClient);
reply = resource.put(body, MediaType.APPLICATION_JSON);
T result = new JacksonConverter().toObject(new JacksonRepresentation<T>(reply, returnType), returnType, resource);
Status status = resource.getStatus();
return new RestletClientResponse<T>(result, (Form)resource.getResponseAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS), status);
} finally {
if (reply != null) {
reply.release();
}
resource.release();
Response.setCurrent(restletResponse);
}
}
}
and RestletClientResponse<T> is:
public class RestletClientResponse<T> {
public T returnObject = null;
public Form responseHeaders = null;
public Status status = null;
public RestletClientResponse(T returnObject, Form responseHeaders, Status status) {
this.returnObject = returnObject;
this.responseHeaders = responseHeaders;
this.status = status;
}
}
and RestletUtils.addResponseHeaders is:
public class RestletUtils {
public static void addResponseHeader(String key, Object value) {
Form responseHeaders = (Form)org.restlet.Response.getCurrent().getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
if (responseHeaders == null) {
responseHeaders = new Form();
org.restlet.Response.getCurrent().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, responseHeaders);
}
responseHeaders.add(key, value.toString());
}
public static void addResponseHeaders(Form responseHeaders) {
for (String headerKey : responseHeaders.getNames()) {
RestletUtils.addResponseHeader(headerKey, responseHeaders.getValues(headerKey));
}
}
}
The problem is that if the two jars run in the same Java process, then an exception thrown from the internal API is not routed to the JAX-RS exception mapper of the internal API - the exception propagates up to the public API and is translated to the Internal Server Error (500).
Which means I am doing it wrong. So, my question is how do I invoke the internal RESTful API from within the public API implementation given the constraint that both the client and the server may run in the same Java process.
Surely, there are other problems, but I have a feeling that fixing the one I have just described is going to fix others as well.
The problem has nothing to do with the fact that both internal and public JARs are in the same JVM. They are perfectly separated by WebResource.put() method, which creates a new HTTP session. So, an exception in the internal API doesn't propagate to the public API.
The internal server error in the public API is caused by the post-processing mechanism, which interprets the output of the internal API and crashes for some reason. Don't blame the internal API, it is perfectly isolated and can't cause any troubles (even though it's in the same JVM).