Get network.request response headers in lua - networking

I’m using network.request like this:
network.request( fullUrl, "POST", networkListener, params)
and receiving the response in my network listener as such:
local function networkListener( event )
if ( event.isError ) then
response = {};
else
response = json.decode(event.response);
end
end
I am receiving the body response of the request but I want to receive the request’s response headers as well. How can I achieve this?
Thanks a lot!

The documentation for network.request says:
network.request( url, method, listener [, params] )
listener (required)
Listener. The listener function invoked at various phases of the HTTP operation. This is passed a networkRequest event.
And the documentation for networkRequest links to event.responseHeaders, which gives this example:
-- Print the Content-Type header value for a response
local function networkListener( event )
print( "Content-Type of response is: " .. event.responseHeaders["Content-Type"] )
end

Related

How to make http request in Apigee JavaScript policy?

I am using Apigee API proxy and in the PreFlow part of the Proxy endpoint I have to make a http request. I created a JavaScript policy, where I tried using fetch to make the request, but when I call the endpoint, the response is ReferenceError: "fetch" is not defined. Does anybody have any suggestions what could work?
Apigee JavaScript Object Model exposes httpClient object.
More detail can be found in the docs .
I set a Variable to be called later and used the httpClient call like so:
//===================================
//== Set Function to pass response ==
//===================================
function onComplete (response, error){
//== Check if HTTP request was successful ==
//==========================================
if(response){
context.setVariable("responsePayload1", response.content);
}
//== Set Error Variable is it fails ==
//====================================
else {
context.setVariable("example.error", "Whoops: "+error)
}}
//==================================
//== Set Variable to run function ==
//==================================
var calloutResponse = httpClient.get("http://yourwebsitename.com/your-call-uri", onComplete);
By setting the variable it forces the JS to run the httpClient.get command in addition to running the above function.

"Handler crashed with error runtime error: invalid memory address or nil pointer dereference", but POSTMAN is ok! Why this happens?

I work with vue and go for frontend and backend respectively. I send post request to my server and get 403 error code message(notAllowed). But in postman I get the objects and is fine.
Vue and Vuex
My axios post request:
const response = await this.$axios.post(`http://localhost:8000/v1/org/${params.organization}/kkms/${params.kkm}/closeShift`,{
headers : {
'token' : this.state.token.value
}});
I know I should also use other properties like 'Content-Type' and etc in headers, but know it works well with only "token" property in the other requests. I want to know whether problem in backend or frontend?
It seems you have a mistake in the axios request.
You are receiving a 403, that means you are not authorized (or sometimes something else, check the comments in the question and down here ).
As can be found in axios docs, the post request looks like this:
axios.post(url[, data[, config]]).
It accepts the config (so the headers) as THIRD parameter, while you are setting it as second parameter. Add an empty FormData object as second param, and just shift your config to the third param.
const fakeData = new FormData();
const response = await this.$axios.post(`http://localhost:8000/v1/org/${params.organization}/kkms/${params.kkm}/closeShift`,
fakeData,
{
headers : {
'token' : this.state.token.value
}
});

Meteor Get request

Bear with me for any mistakes/wrong terminology since I am new to all this. I am using meteor to develop my project and i need to make a get request to an external API. (I already added meteor add http) Below is my code:
HTTP.call( 'GET', 'url', {}, function( error, response ) {
if ( error ) {
console.log( error );
} else {
console.log( response );
}
});
If i use the code inside my Client folder in Meteor I get the following error No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access meteor It has something to do with CORS which I didn't understand how to implement. If I use the code above in my Server side I do get the correct response in the console but how do I use it as a var on my client javascript code?
Tou can use .call function of HTTP and pass your header in options:
HTTP.call(method, url, [options], [asyncCallback])
Arguments
method String
The HTTP method to use, such as "GET", "POST", or "HEAD".
url String
The URL to retrieve.
asyncCallback Function
Optional callback. If passed, the method runs asynchronously, instead of synchronously, and calls asyncCallback. On the client, this callback is required.
Options
content String
String to use as the HTTP request body.
data Object
JSON-able object to stringify and use as the HTTP request body. Overwrites content.
query String
Query string to go in the URL. Overwrites any query string in url.
params Object
Dictionary of request parameters to be encoded and placed in the URL (for GETs) or request body (for POSTs). If content or data is specified, params will always be placed in the URL.
auth String
HTTP basic authentication string of the form "username:password"
headers Object
Dictionary of strings, headers to add to the HTTP request.
timeout Number
Maximum time in milliseconds to wait for the request before failing. There is no timeout by default.
followRedirects Boolean
If true, transparently follow HTTP redirects. Cannot be set to false on the client. Default true.
npmRequestOptions Object
On the server, HTTP.call is implemented by using the npm request module. Any options in this object will be passed directly to the request invocation.
beforeSend Function
On the client, this will be called before the request is sent to allow for more direct manipulation of the underlying XMLHttpRequest object, which will be passed as the first argument. If the callback returns false, the request will be not be send.
Souce: Here
Fixed it. On client side
Meteor.call("getURL",'url',{},function(err,res){
if(err){
console.log('Error: '+err);
}
if(!err){
console.log('Response: '+res);
}
and on server
Meteor.methods({
'getURL': function(url_l){
console.log("Request: "+url_l)
return HTTP.get(url_l)
}
});

How to Read the message Body in a HTTP POST in Netty (version >= 4.x)

In my server handler;
- channelRead() always gets the msg as HTTPRequest and there I cannot find any place to get the POST request payload.
Then I tried following in my handler to check if it works. The decoder has 0 elements.
HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(new DefaultHttpDataFactory(false), request);
In my server pipeline I have HttpServerCodec and a custom handler only.
It's likely that your HTTP request is chunked. You should try to add an io.netty.handler.codec.http.HttpObjectAggregator to your pipeline, just after the codecs. It will give a FullHttpRequest to your handler.
ChannelPipeline p = ...;
...
p.addLast("encoder", new HttpResponseEncoder());
p.addLast("decoder", new HttpRequestDecoder());
p.addLast("aggregator", new HttpObjectAggregator(1048576));
...
p.addLast("handler", new MyServerHandler());
Alternatively, you could check this example where HttpRequest and HttpContent are handled separately.
As Leo Gomes mentioned, HTTP Request maybe chunked. so add HttpObjectAggregator before your own handler in pipeline.
if HTTP POST request body is Simple Json String. You can parse it in your own handler like this:
private String parseJosnRequest(FullHttpRequest request){
ByteBuf jsonBuf = request.content();
String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8);
return jsonStr;
}

How do I inject new request header with json data in proxy request flow?

I am trying to inject a new request header in the proxy request flow using JS policy to be sent to the backend server. When I look at the debug trace, I see that the json data in the request header is distorted.
I am trying to inject some string like
{"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}}
But when I look at the trace window I see this
{"scope":"","time_till":2264,id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM,"custom_data":{"c_id":"test_data"}}
what am I doing wrong?
var obj = {"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}};
var header_str = JSON.stringify(obj);
context.setVariable('json-header',header_str);
request.headers['x-json-hedar']= header_str;
I tested your code and it seems to work. Here's an example response where I set the header string as a response:
HTTP/1.1 200 OK
User-Agent: curl/7.30.0
Accept: */*
x-json-header: {"scope":"","time_till":2264,"id_1":"hUXLXVqpA1J4vA9sayk2UttWNdM","custom_data":{"c_id":"test_data"}}
Content-Length: 0
It appears this is only an issue with the Apigee debug session / trace tool as the header value was set correctly. Here was the JSON download of the debug session showing this header value:
{
"name": "x-json-header",
"value": "{\"scope\":\"\",\"time_till\":2264,id_1\":\"hUXLXVqpA1J4vA9sayk2UttWNdM,\"custom_data\":{\"c_id\":\"test_data\"}}"
}
You can see that the value passed to the UI for displaying the debug info has the malformed json:
id_1\":\"hUXLXVqpA1J4vA9sayk2UttWNdM,
This does not appear to be a problem with the Apigee debug/trace UI. I see the malformed JSON trickle down to my backend service.
Here is the header I'm trying to send -
{"timeStamp":"2349218349381274","latitude":"34.589","longitude":"-37.343","clientIp":"127.0.0.0","deviceId":"MOBILE_TEST_DEVICE_AGAIN","macAddress":"23:45:345:345","deviceType":"phone","deviceOS":"iOS","deviceModel":"iPhone 5S","connection":"5G","carrier":"Vodafone","refererURL":"http://www.google.com","xforwardedFor":"129.0.0.0","sessionId":"kfkls498327ksdjf","application":"mobile-app","appVersion":"7.6.5","serviceVersion":"1.0","userAgent":"Gecko"}
But Apigee reads the header as below. Note the missing start quotes from some fields.
{"timeStamp":"2349218349381274",latitude":"34.589,longitude":"-37.343,clientIp":"127.0.0.0,deviceId":"MOBILE_TEST_DEVICE_AGAIN,macAddress":"23:45:345:345,deviceType":"phone,deviceOS":"iOS,deviceModel":"iPhone 5S,connection":"5G,carrier":"Vodafone,refererURL":"http://www.google.com,xforwardedFor":"129.0.0.0,sessionId":"kfkls498327ksdjf,application":"mobile-app,appVersion":"7.6.5,serviceVersion":"1.0,"userAgent":"Gecko"}
The header is used in a service callout to a backend service which parses it. And rightly so, I get the below error -
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('l' (code 108)): was expecting double-quote to start field name
at [Source: java.io.StringReader#22549cdc; line: 1, column: 35]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1378)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:599)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:520)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleUnusualFieldName(ReaderBasedJsonParser.java:1275)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._parseFieldName(ReaderBasedJsonParser.java:1170)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:611)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:301)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2796)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1942)
I encounter strange behaviour when adding JSON to a context variable for example like the following:
var header_str = JSON.stringify(obj);
context.setVariable('json-header',header_str);
I appreciate this is an example so you may not have included the full extent of the problem but this normally works (now it is not added to a variable first):
request.headers['x-json-header'] = JSON.stringify(obj);
Code like this also works if you can send the request from JavaScript
var headers = {"Accept": "application/json", "Accept-Language": "en"};
var sessionRequest = new Request(url, 'POST', headers, body);
var exchange = httpClient.send(sessionRequest);
exchange.waitForComplete()
if (exchange.isSuccess()){
var responseObj = exchange.getResponse().content.asJSON;
if (responseObj.error){
request.content += JSON.stringify(responseObj);
}
}
Also, I have had success with using an AssignMessage policy to build a request, followed by a Callout policy to read the stored request and then make that request and store the result in a response object which can then be read by an Extract Variables policy.

Resources