Fiddler - intercept request return different response - fiddler

In Fiddler I have some custom rules that upon getting a certain response from the server, it sends out a new request automatically:
static function OnBeforeResponse(oSession: Session) {
...
if (oSession.uriContains("something.aspx")) {
var requestB = "..."
FiddlerObject.utilIssueRequest(requestB);
}
...
}
I want to intercept a requestA from the client, wait until I have received a response back for requestB, and then return requestB's response for requestA. Does anyone know of a way to accomplish this?

You may want to try the function FiddlerApplication.oProxy.SendRequestAndWait like this:
static function OnBeforeResponse(oSession: Session)
{
...
if (oSession.uriContains("something.aspx"))
{
var oSD = new System.Collections.Specialized.StringDictionary();
var GetResquestBAnswer : Session = FiddlerApplication.oProxy.SendRequestAndWait(RequestB.oRequest.headers, RequestB.requestBodyBytes, oSD, null);
if (200 == GetResquestBAnswer.responseCode)
{
oSession.ResponseBody=GetResquestBAnswer.ResponseBody;
}
}
...
}

Related

What should I do to get database response from this vertx code

This is the method used for database connection and obtain results:
public Future<String> getDatabaseUsers(JDBCClient client) {
return Future.future(pHandler -> {
client.getConnection(res -> {
if (res.succeeded()) {
SQLConnection con = res.result();
con.query("select u.id, u.name from users u", rHandler -> {
String data;
if (rHandler.succeeded()) {
data = Json.encode(rHandler.result().getResults());
} else {
data = "Database execution error";
}
con.close();
pHandler.complete(data);
});
} else {
pHandler.complete("Cannot connect to database");
}
});
});
}
This is the caller method:
private void handleRequest(RoutingContext routingContext, JDBCClient client,
Handler<List<String>> resultHandler) {
routingContext.vertx().<String>executeBlocking(pHandler -> {
pHandler.complete(getDatabaseUsers(client).result());
}, ar -> {
List<String> responses = new ArrayList<>();
if (ar.succeeded()) {
responses.add(ar.result());
System.out.println(Json.encode(responses)); // Null here
}
resultHandler.handle(responses);
});
}
The resultHandler object is used to add more responses from other processes; but this is not the problem actually.
And this is the endpoint:
router.get("/db").handler(ctx -> handleRequest(
ctx, client, (list) -> ctx.response()
.putHeader("Content-Type", "text/plain")
.end(Json.encode(list))));
The problem with this code, is that service response is [null] and the database method is not accomplished yet.
So, what should I do to wait for database response and then send the response to the client?
There are a number of issues with this code:
getDatabaseUsers swallows errors. You probably want to do pHandler.fail(res.failure()); or something similar.
This code: pHandler.complete(getDatabaseUsers(client).result()); is not doing what you think it's doing. result() doesn't block, so you complete your future with another unfishined future.
What you actually want is the reverse:
getDatabaseUsers(client).handle((r) -> { // This is called when the futures actually completes
if (r.succeeded()) {
pHandler.complete(r.result());
}
...
});
I would really recommend going over this guide, as it covers exactly your case.

Refreshing access token with multiple requests

Im struggling with getting axios interceptors to work.
When my token expires, i need it to refresh the access token and retry the original request once the token is refreshed.
I have this part working.
The problem is if i have concurrent api calls it will only retry the first request when the token was first invalid.
Here is my interceptor code:
export default function execute() {
let isRefreshing = false
// Request
axios.interceptors.request.use(
config => {
var token = Storage.getAccessToken() //localStorage.getItem("token");
if (token) {
console.log('Bearer ' + token)
config.headers['Authorization'] = 'Bearer ' + token
}
return config
},
error => {
return Promise.reject(error)
}
)
// Response
axios.interceptors.response.use(
response => {
return response
},
error => {
const originalRequest = error.config
// token expired
if (error.response.status === 401) {
console.log('401 Error need to reresh')
originalRequest._retry = true
let tokenModel = {
accessToken: Storage.getAccessToken(),
client: 'Web',
refreshToken: Storage.getRefreshToken()
}
//Storage.destroyTokens();
var refreshPath = Actions.REFRESH
if (!isRefreshing) {
isRefreshing = true
return store
.dispatch(refreshPath, { tokenModel })
.then(response => {
isRefreshing = false
console.log(response)
return axios(originalRequest)
})
.catch(error => {
isRefreshing = false
console.log(error)
// Logout
})
} else {
console.log('XXXXX')
console.log('SOME PROBLEM HERE') // <------------------
console.log('XXXXX')
}
} else {
store.commit(Mutations.SET_ERROR, error.response.data.error)
}
return Promise.reject(error)
}
)
}
I'm not sure what i need in the else block highlighted above.
EDIT:
When I do
return axios(originalRequest)
in the else block it works, however im not happy with the behaviours. It basically retries all the requests again and again until the token is refreshed.
I would rather it just retried once after the token had been refreshed
Any ideas
Thanks
You can just have additional interceptor which can refresh token and execute your pending requests.
In this, countDownLatch class can help.
Here is sample Interceptor code,
class AutoRefreshTokenRequestInterceptorSample() : Interceptor {
companion object {
var countDownLatch = CountDownLatch(0)
var previousAuthToken = ""
const val SKIP_AUTH_TOKEN = "SkipAccessTokenHeader"
const val AUTHORIZATION_HEADER = "AUTHORIZATION_HEADER_KEY"
}
#Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response? {
val request = chain.request()
if (shouldExecuteRequest(request)) {
// Execute Request
val response = chain.proceed(request)
if (!response.isSuccessful) {
// Failed Case
val errorBody = response.peekBody(java.lang.Long.MAX_VALUE).string()
val error = parseErrorModel(errorBody)
// Gives Signal to HOLD the Request Queue
countDownLatch = CountDownLatch(1)
handleError(error!!)
// After updating token values, execute same request with updated values.
val updatedRequest = getUpdatedRequest(request)
// Gives Signal to RELEASE Request Queue
countDownLatch.countDown()
//Execute updated request
return chain.proceed(updatedRequest)
} else {
// success case
return response
}
}
// Change updated token values in pending request objects and execute them!
// If Auth header exists, and skip header not found then hold the request
if (shouldHoldRequest(request)) {
try {
// Make this request to WAIT till countdown latch has been set to zero.
countDownLatch.await()
} catch (e: Exception) {
e.printStackTrace()
}
// Once token is Updated, then update values in request model.
if (previousAuthToken.isNotEmpty() && previousAuthToken != "newAccessToken") {
val updatedRequest = getUpdatedRequest(request)
return chain.proceed(updatedRequest)
}
}
return chain.proceed(request)
}
private fun handleError(error: ErrorDto) {
// update your token as per your error code logic
//Here it will make new API call to update tokens and store it in your local preference.
}
/***
* returns Request object with updated token values.
*/
private fun getUpdatedRequest(request: Request): Request {
var updateAuthReqBuilder: Request.Builder = request.newBuilder()
var url = request.url().toString()
if (url.contains(previousAuthToken.trim()) && previousAuthToken.trim().isNotEmpty()) {
url = url.replace(previousAuthToken, "newAccessToken")
}
updateAuthReqBuilder = updateAuthReqBuilder.url(url)
// change headers if needed
return updateAuthReqBuilder.build()
}
private fun shouldExecuteRequest(request: Request) =
shouldHoldRequest(request) && isSharedHoldSignalDisabled()
/**
* If count down latch has any value then it is reported by previous request's error signal to hold the whole pending chain.
*/
private fun isSharedHoldSignalDisabled() = countDownLatch.count == 0L
private fun shouldHoldRequest(request: Request) = !hasSkipFlag(request) && hasAuthorizationValues(request)
private fun hasAuthorizationValues(request: Request) = isHeaderExist(request, AUTHORIZATION_HEADER)
private fun hasSkipFlag(request: Request) = isHeaderExist(request, SKIP_AUTH_TOKEN)
private fun isHeaderExist(request: Request, headerName: String): Boolean {
return request.header(headerName) != null
}
private fun parseErrorModel(errorBody: String): Error? {
val parser = JsonParser()
// Change this logic according to your requirement.
val jsonObject = parser.parse(errorBody).asJsonObject
if (jsonObject.has("Error") && jsonObject.get("Error") != null) {
val errorJsonObj = jsonObject.get("Error").asJsonObject
return decodeErrorModel(errorJsonObj)
}
return null
}
private fun decodeErrorModel(jsonObject: JsonObject): Error {
val error = Error()
// decode your error object here
return error
}
}
This is how I do:
let isRefreshing = false;
let failedQueue = [];
const processQueue = (error, token = null) => {
failedQueue.forEach(prom => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});
failedQueue = [];
};
axios.interceptors.response.use(
response => response,
error => {
const originalRequest = error.config;
if (error.response.status === 400) {
// If response is 400, logout
store.dispatch(logout());
}
// If 401 and I'm not processing a queue
if (error.response.status === 401 && !originalRequest._retry) {
if (isRefreshing) {
// If I'm refreshing the token I send request to a queue
return new Promise((resolve, reject) => {
failedQueue.push({ resolve, reject });
})
.then(() => {
originalRequest.headers.Authorization = getAuth();
return axios(originalRequest);
})
.catch(err => err);
}
// If header of the request has changed, it means I've refreshed the token
if (originalRequest.headers.Authorization !== getAuth()) {
originalRequest.headers.Authorization = getAuth();
return Promise.resolve(axios(originalRequest));
}
originalRequest._retry = true; // mark request a retry
isRefreshing = true; // set the refreshing var to true
// If none of the above, refresh the token and process the queue
return new Promise((resolve, reject) => {
// console.log('REFRESH');
refreshAccessToken() // The method that refreshes my token
.then(({ data }) => {
updateToken(data); // The method that sets my token to localstorage/Redux/whatever
processQueue(null, data.token); // Resolve queued
resolve(axios(originalRequest)); // Resolve current
})
.catch(err => {
processQueue(err, null);
reject(err);
})
.then(() => {
isRefreshing = false;
});
});
}
return Promise.reject(error);
},
);
I don't know what is the schema of your token (after decrypted) but one of the attributes which is a good practice to keep is the exp "expiration_date".
Said so, having the expiration date you can know when you should refresh your token.
Without understanding your architecture is hard to inform the right solution. But let's say you are doing everything manually, usually onIdle/onActive is when we check if the user session is still ok, so at this time you could use the token info to know if you should refresh its value.
It is important to understand this process because the token should be refreshed only if the user is constantly active and it is about to expire (like 2min before).
Please refer to angular version of the code for which i was facing the same problem and after changing many approaches this was my final code which is working at its best.
Re Initaite the last failed request after refresh token is provided

AWS Lambda - MongoDB resource optimization

I'm building facebook chatbot using AWS Lambda and MongoDB. At the moment, my application is pretty simple but I'm trying to nail down the basics before I move onto the complex stuff.
I understand AWS Lambda is stateless but I've read adding below line in handler along with variables initialized outside handler, I don't have to establish DB connection on every request.
context.callbackWaitsForEmptyEventLoop = false;
(I've read this from this article; https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs)
I'm adding my entire code below
'use strict'
const
axios = require('axios'),
mongo = require('mongodb'),
MongoClient = mongo.MongoClient,
assert = require('assert');
var VERIFY_TOKEN = process.env.VERIFY_TOKEN;
var PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
var MONGO_DB_URI = process.env.MONGO_DB_URI;
let cachedDb = null;
let test = null;
exports.handler = (event, context, callback) => {
var method = event.context["http-method"];
context.callbackWaitsForEmptyEventLoop = false;
console.log("test :: " + test);
if (!test) {
test = "1";
}
// process GET request --> verify facebook webhook
if (method === "GET") {
var queryParams = event.params.querystring;
var rVerifyToken = queryParams['hub.verify_token']
if (rVerifyToken === VERIFY_TOKEN) {
var challenge = queryParams['hub.challenge'];
callback(null, parseInt(challenge))
} else {
var response = {
'body': 'Error, wrong validation token',
'statusCode': 403
};
callback(null, response);
}
// process POST request --> handle message
} else if (method === "POST") {
let body = event['body-json'];
body.entry.map((entry) => {
entry.messaging.map((event) => {
if (event.message) {
if (!event.message.is_echo && event.message.text) {
console.log("BODY\n" + JSON.stringify(body));
console.log("<<MESSAGE EVENT>>");
// retrieve message
let response = {
"text": "This is from webhook response for \'" + event.message.text + "\'"
}
// facebook call
callSendAPI(event.sender.id, response);
// store in DB
console.time("dbsave");
storeInMongoDB(event, callback);
}
} else if (event.postback) {
console.log("<<POSTBACK EVENT>>");
} else {
console.log("UNHANDLED EVENT; " + JSON.stringify(event));
}
})
})
}
}
function callSendAPI(senderPsid, response) {
console.log("call to FB");
let payload = {
recipient: {
id: senderPsid
},
message: response
};
let url = `https://graph.facebook.com/v2.6/me/messages?access_token=${PAGE_ACCESS_TOKEN}`;
axios.post(url, payload)
.then((response) => {
console.log("response ::: " + response);
}).catch(function(error) {
console.log(error);
});
}
function storeInMongoDB(messageEnvelope, callback) {
console.log("cachedDB :: " + cachedDb);
if (cachedDb && cachedDb.serverConfig.isConnected()) {
sendToAtlas(cachedDb.db("test"), messageEnvelope, callback);
} else {
console.log(`=> connecting to database ${MONGO_DB_URI}`);
MongoClient.connect(MONGO_DB_URI, function(err, db) {
assert.equal(null, err);
cachedDb = db;
sendToAtlas(db.db("test"), messageEnvelope, callback);
});
}
}
function sendToAtlas(db, message, callback) {
console.log("send to Mongo");
db.collection("chat_records").insertOne({
facebook: {
messageEnvelope: message
}
}, function(err, result) {
if (err != null) {
console.error("an error occurred in sendToAtlas", err);
callback(null, JSON.stringify(err));
} else {
console.timeEnd("dbsave");
var message = `Inserted a message into Atlas with id: ${result.insertedId}`;
console.log(message);
callback(null, message);
}
});
}
I did everything as instructed and referenced a few more similar cases but somehow on every request, "cachedDb" value is not saved from previous request and the app is establishing the connection all over again.
Then I also read that there is no guarantee the Lambda function is using the same container on multiple requests so I made another global variable "test". "test" variable value is logged "1" from the second request which means it's using the same container but again, "cachedDb" value is not saved.
What am I missing here?
Thanks in advance!
In short AWS Lambda function is not a permanently running service of any kind.
So, far I know AWS Lambda works on idea - "one container processes one request at a time".
It means when request comes and there is available running container for the Lambda function AWS uses it, else it starts new container.
If second request comes when first container executes Lambda function for first request AWS starts new container.
and so on...
Then there is no guarantee in what container (already running or new one) Lambda function will be executed, so... new container opens new DB connection.
Of course, there is an inactivity period and no running containers will be there after that. All will start over again by next request.

How can I do this redirection from ballerinalang?

I've implemented a REST endpoint in ballerinalang called https://localhost:9090/isValidUser. And here is my code below
import ballerina.net.http;
#http:configuration {
basePath:"/",
httpsPort:9090,
keyStoreFile:"${ballerina.home}/bre/security/wso2carbon.jks",
keyStorePassword:"wso2carbon",
certPassword:"wso2carbon",
trustStoreFile:"${ballerina.home}/bre/security/client-truststore.jks",
trustStorePassword:"wso2carbon"
}
service<http> authentication {
#http:resourceConfig {
methods:["POST"],
path:"/isValidUser"
}
resource isValidUser (http:Request req, http:Response res) {
println(req.getHeaders());
res.send();
}
}
Now I need to do is when I invoke that URL from the browser, I need to redirect the user to another URL called https://localhost:3000 after some validations happen within my service.
So how can I do this redirection from ballerinalang?
Ballerina has provided smooth API to do the redirection. Please check following code which elaborates the Listener endpoint redirection.
service<http:Service> redirect1 bind {port:9090} {
#http:ResourceConfig {
methods:["GET"],
path:"/"
}
redirect1 (endpoint client, http:Request req) {
http:Response res = new;
_ = client -> redirect(res, http:REDIRECT_TEMPORARY_REDIRECT_307,
["http://localhost:9093/redirect2"]);
}
}
The complete example is available in
Ballerina Redirects
In Ballerina, you need to handle the redirects yourself by setting the necessary headers and status code. The following example is a simple demo of how you can redirect in Ballerina. (note: I tried this in Ballerina 0.95.2)
import ballerina.net.http;
#http:configuration {basePath:"/hello"}
service<http> helloWorld {
#http:resourceConfig {
methods:["GET"],
path:"/"
}
resource sayHello (http:Request request, http:Response response) {
map qParams = request.getQueryParams();
var name, _ = (string)qParams.name;
if (isExistingUser(name)) {
response.setStringPayload("Hello Ballerina!");
} else {
response.setHeader("Location", "http://localhost:9090/hello/newUser");
response.setStatusCode(302);
}
_ = response.send();
}
#http:resourceConfig {path:"/newUser"}
resource newUser (http:Request request, http:Response response) {
string msg = "New to Ballerina? Welcome!";
response.setStringPayload(msg);
_ = response.send();
}
}
function isExistingUser (string name) (boolean) {
return name == "Ballerina";
}

How can I DRY up my service in Angular 2

I'm working on a Angular 2 service and I'm trying to DRY up my code. My service returns data from an RESTful API (GET request). For the moment i only send one param (auth_token) but how can i deal with a call to my service with extra params ?
Here my basic call to my service:
this._dashboardService.getData('users')
.subscribe(usersData=> {
if (usersData.ok) {
this.users= usersData.json();
});
Here is my service :
getData(data) {
let authToken = localStorage.getItem('auth_token');
let params = new URLSearchParams();
params.set('auth_token', authToken);
return this._http
.get(this._url+data,{ search: params })
.map(data=> {
if (data.status===200) {
return data;
}
});
}
I want to make this code work :
this._dashboardService.getData('users',oneParameter)
.subscribe(usersData=> {
if (usersData.ok) {
this.users= usersData.json();
});
I'm not sure how to proceed to make this (is it even possible ?)
Any ideas ?
You can pass your new object param and assign to another object that contains the auth_token.
getData(data, anotherParams) {
let params = new URLSearchParams();
let authToken = localStorage.getItem('auth_token');
var myObject = Object.assign({'auth_token':authToken}, anotherParams);
for (var name in myObject) {
params.set(name, myObject[name]);
}
return this._http
.get(this._url+data,{ search: params })
.map(data=> {
if (data.status===200) {
return data;
}
});
}