Browser-Mob Intercepting multiple requests with same url but want to send back different response - browsermob-proxy

I want to intercept requests in my application and one of the scenarios I have come across is that - due to nature of the application some of the services have same request endpoint different payload though and I want to send back different responses at different occurrence. Is there a way to assign order to the intercepted request and send a specific response as per the sequence? or any other mechanism to tell browser-mob that example - for this url with this payload send this response? Because if it is the same url then responses are overridden by the last intercepted request.
I have already tried request with url and contents contains. Check the if condition in code below.
proxy.addRequestFilter((request, contents, messageInfo) -> {
String content = null;
try {
content = URLDecoder.decode(contents.getTextContents(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (request.getUri().contains(endpoint) && (content != null && content.contains(contentContains))) {
//Use DefaultFullHttpResponse for posting the json body
final HttpResponse httpResponse = new DefaultFullHttpResponse(request.getProtocolVersion(),
statusCode);
//Close the connection so it doesn't pass through
httpResponse.headers().add("CONNECTION", "Close");
//Specify the content-type and charset
httpResponse.headers().add("Content-Type", "application/json; charset=UTF-8");
//replace the body
HttpObjectUtil.replaceTextHttpEntityBody((FullHttpMessage) httpResponse, response);
return httpResponse;
}
return null;
});
Actual - If the two request have same endpoint the last intercepted request overrides the response I want to send back.
Expected- Some mechanism where Bowsermob is able to register different responses for the request with same end point and send back different response.

Related

Checking response code of all URLs in a column [Airtable database]

We have an airtable database of over 24000 records. These records are websites, and many now have errors in them (missing "/", extra space...). We are trying to detect the websites that have these errors before manually fixing them.
What we have tried
So far, we have used the fetch method to call each URL and report back on the error status . This is the script we have used:
const inputConfig = input.config();
const url = inputConfig.url;
let status;
try {
const response = await fetch(url);
status = response.status; } catch (error) {
status = 'error'; }
output.set('status', status);
Issues we ran into
The script won't follow redirects, so it reports "error" back if there is a redirect even if the URL is working.
The output now is either "200" meaning the URL works, or "error". We don't get the actual response code of the error, which we ideally would like to get.
Any help would be appreciated! Thanks
There's some nuance to how fetch works. If you review Mozilla's documentation they say:
The Promise returned from fetch() won't reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, as soon as the server responds with headers, the Promise will resolve normally (with the ok property of the response set to false if the response isn't in the range 200–299), and it will only reject on network failure or if anything prevented the request from completing.
So you have to do an extra check in your code to determine if the request was successful or not and throw your own error. In your case, you don't necessarily need to throw an error at all and can just rely on ok property of the response.
const config = input.config();
const url = config.url;
let status = null;
const response = await fetch(url);
if(response.ok) {
status = response.status
} else {
status = 'error'
}
output.set('status', status);

PostAsJsonAsync does not return response and eventually times out

I have an MVC website that makes an API call using a HttpClient. I configured the timeout to be 2 minutes and the API call generally returns within 90 seconds. I can see from application logging that the API completes its execution. If I also call the API method using a tool like Postman or SOAPUI I get a JSON response after 90 seconds.
I cannot get my MVC application to return the response and instead after 2 minutes it will throw an OperationCanceledException which I catch.
public async Task<CommonApiResult> PostAsync<T>(string url, TimeSpan timeout, T payload)
{
using (var client = new HttpClient())
{
client.Timeout = timeout;
var response = await client.PostAsJsonAsync(url, payload);
if (response.IsSuccessStatusCode)
{
var stringContent = await response.Content.ReadAsString(url).ConfigureAwait(false);
return new CommonApiResult<T>
{
StatusCode = response.StatusCode,
Data = stringContent.Deserialize<T>(url)
};
}
}
return null;
}
I never get to the code if (response.IsSuccessStatusCode).
Is there something obvious I am doing wrong? I have looked at a lot of questions and they all seem to be incorrectly using. Result and not using await like me.
just in case someone visit this link in the future.
if it is called via like button click event please check does the button in form tag and has type submit. if yes remove it from the tag

IBM DataPower - How to handle HTML Response from openurl?

I tried looking for the solution in the forum but I was unable to find something similar to what I'm trying to achieve. I have a gateway script in an MPG which kinda looks like this:
session.INPUT.readAsJSON(function (error, json) {
if (error){
throw error;
} else {
var SAMLResponse = json['SAMLResponse'];
var RelayState = json['RelayState'];
var urlopen = require('urlopen');
var options = {
target: 'https://************.com/e32d32der2tj90g8h4',
method: 'POST',
headers: { 'HEADER_NAME' : 'VALUE'},
contentType: 'application/json',
timeout: 60,
sslClientProfile: 'ClientProfile',
data: {"SAMLResponse": SAMLResponse, "RelayState": RelayState}
};
urlopen.open(options, function(error, response) {
if (error) {
session.output.write("urlopen error: "+JSON.stringify(error));
} else {
var responseStatusCode = response.statusCode;
var responseReasonPhrase = response.reasonPhrase;
response.readAsBuffer(function(error, responseData){
if (error){
throw error;
} else {
session.output.write(responseData);
console.log(responseData);
}
});
}
});
}
});
I'm doing a POST request and the response I get from the urlopen function is an HTML page, how to I display the contents of that page in my browser? I need that to initiate a process flow. am I going in the wrong direction here? what's the best way to POST to a URI and display it's response in DataPower?
with regards to my experience with DataPower, I just started learning, So I might not be familiar with many of the concepts.
Thanks in Advance!
session.INPUT.readAsJSON() would indicate that you are receiving JSON data as the input (from the POST).
Since you are building this in a Multi-Protocol Gateway (MPGW) you need to set the Response type to non-xml if the response is HTML and if there is no backend call being made (other than the url-open()) you also must set the skip-backside=1 variable.
Is the scenario as:
JSON HTTP Request -> [MPGW] -> url-open() -> Backend server --|
HTTP Response <-----------------------------------------|
Or:
JSON HTTP Request -> [MPGW] -> url-open() --| (skip-backside)
HTTP Response <------------------------|
If there is no backend call I would recommend building this in a XML Firewall (XMLFW) service instead and set it to "loopback" and non-xml.
If there is a backend and that is where you are sending your HTML from the url-open() then only MPGW Response type needs to be set to non-xml.
If it is the second option the you can just set the payload and headers in GWS and just call the target (https://************.com/e32d32der2tj90g8h4) as teh MPGW backside connection, no need for the url-open().

How do you add CORS headers in Redstone interceptor?

I'm trying to add CORS headers to incoming requests but I've noticed that app.response.headers is an immutable map and app.request.response doesn't exist even though it appears in the documentation examples. So, to the OPTIONS request I'm replying using a new Shelf response, but I can't find a way to add any new headers to the response of the actual request. Any ideas?
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
// app.request.response is not available
app.request.response.headers.add('Access-Control-Allow-Origin', '*');
app.chain.next();
}
}
I found the fix in the first piece of code inside the Interceptor documentation...:)
#app.Interceptor(r"/api/.*", chainIdx: 1)
corsInterceptor() {
if (app.request.method == "OPTIONS") {
var response = new shelf.Response.ok("", headers: HEADERS);
app.chain.interrupt(statusCode: HttpStatus.OK, responseValue: response);
} else {
app.chain.next(() => app.response.change(headers: HEADERS));
}
}
app.chain.next() can take a callback as argument, which is expected to return a Response object. In this case app.response.change() returns a response with the correct headers.

Dart Client HttpRequest error/authentication handling

I have a Dart client and a Java backend. I'm trying to add security around my application, so the Java server requires the user to be authenticated before accessing data. If a webservice call comes in and the user is not authenticated the backend services send a redirect with a HttpResponseCode (401) back to the client call. I have it now that the client can parse the request.status and see the 401 but it doesn't handle the redirect.
Dart Code
HttpRequest request=new HttpRequest();
request.onReadyStateChange.listen((_) {
if (request.readyState == HttpRequest.DONE &&
(request.status == 200 || request.status == 0)) {
onHistoryLoaded(request.responseText);
}
});
request.open("GET", url);
request.send();
request.onLoadEnd.listen((e) => processRequest(request));
request.onError.listen((Object error)=>handleError(error));
void processRequest(HttpRequest request) {
var status = request.status;
print("status $status"); //401
}
void handleTheError(Error e){
print("handleTheError Request error: $e");
}
Java Server
//Tried both of these
// response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
// response.sendRedirect(LOGIN_PAGE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("Location", LOGIN_PAGE);
Any suggestions would be great.
Thanks
First of all, the Location header is only allowed with HTTP status codes 201 and some 3xx codes. Instead, in a valid HTTP response, status code 401 requires to send the "WWW-Authenticate" header field - which is probably not what you want. That's the reason your redirect isn't followed automatically.
If your client is the only one to connect to the server and you don't care about the malformed response, you can read the headers on your client with getResponseHeader("Location")
Or you could just use HTTP status 307 instead.

Resources