I need to get response body eg. the response html code from url i am using following code.
location /configure/result.php {
log_by_lua_block {
ngx.log(ngx.ERR, "REQUEST capturing started")
json = require "json"
function getval(v, def)
if v == nil then
return def
end
return v
end
local data = {
request={},
response={}
}
local req = data.request
local resp = data.response
req["host"] = ngx.var.host
req["uri"] = ngx.var.uri
req["headers"] = ngx.req.get_headers()
req["time"] = ngx.req.start_time()
req["method"] = ngx.req.get_method()
req["get_args"] = ngx.req.get_uri_args()
req["post_args"] = ngx.req.get_post_args()
req["body"] = ngx.var.request_body
content_type = getval(ngx.var.CONTENT_TYPE, "")
resp["headers"] = ngx.resp.get_headers()
resp["status"] = ngx.status
resp["duration"] = ngx.var.upstream_response_time
resp["time"] = ngx.now()
resp["body"] = ngx.var.response_body -- Problem Here
ngx.log(ngx.CRIT, json.encode(data));
}
}
But it does not log the response data it recieved from that url eg. the processed source code how could i get the response.data?
My idea is to get response data then use regEx to read specifiq value from the source code which will then do x-y
I cannot test this now, but maybe response is unaccessible during the log phase of request processing?
You can try to get response data within the body_filter_by_lua_block using 'ngx.ctx' table:
body_filter_by_lua_block {
ngx.ctx.response_body = ngx.arg[1]
}
and then use it within the log_by_lua_block block:
log_by_lua_block {
...
resp["body"] = ngx.ctx.response_body
ngx.log(ngx.CRIT, json.encode(data))
}
(please note this is just a guess, please let me know if this works)
Related
I am using Vertx. 4.0.3 and trying to stream a request body directly to a file. For that purpose I am using the following (Kotlin) code:
router.post("/upload").handler { ctx ->
val startTime = System.currentTimeMillis()
val response = ctx.response()
val request = ctx.request()
val fs = vertx.fileSystem()
fs.open("data.bin", OpenOptions()) { res ->
if (res.succeeded()) {
val asyncFile = res.result()
request.pipeTo(asyncFile).onComplete { writeResult ->
if(writeResult.succeeded()) {
response.end("${System.currentTimeMillis() - startTime}")
} else {
response.setStatusCode(500).end(res.cause().stackTraceToString())
}
}
} else {
response.setStatusCode(500).end(res.cause().stackTraceToString())
}
}
}
Unfortunately I am getting an exception like:
java.lang.IllegalStateException: Request has already been read
at io.vertx.core.http.impl.Http1xServerRequest.checkEnded(Http1xServerRequest.java:628)
at io.vertx.core.http.impl.Http1xServerRequest.endHandler(Http1xServerRequest.java:334)
at io.vertx.core.http.impl.Http1xServerRequest.endHandler(Http1xServerRequest.java:60)
at io.vertx.core.streams.impl.PipeImpl.<init>(PipeImpl.java:35)
at io.vertx.core.streams.ReadStream.pipeTo(ReadStream.java:119)
at io.vertx.ext.web.impl.HttpServerRequestWrapper.pipeTo(HttpServerRequestWrapper.java:410)
at fileupload.AppKt$main$2$1.handle(App.kt:60)
at fileupload.AppKt$main$2$1.handle(App.kt)
at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:124)
at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:497)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
Since I do nothing to the request I have no idea where my request is already read. Can someone please give me some insights into this? Thanks!
This happens because by the time the callback of fs.open is invoked, the request has been fully read already.
You must pause the request before opening the file and resume it after:
router.post("/upload").handler { ctx ->
val startTime = System.currentTimeMillis()
val response = ctx.response()
val request = ctx.request()
val fs = vertx.fileSystem()
// Pause
request.pause()
fs.open("data.bin", OpenOptions()) { res ->
// Resume
request.resume()
if (res.succeeded()) {
val asyncFile = res.result()
request.pipeTo(asyncFile).onComplete { writeResult ->
if(writeResult.succeeded()) {
response.end("${System.currentTimeMillis() - startTime}")
} else {
response.setStatusCode(500).end(res.cause().stackTraceToString())
}
}
} else {
response.setStatusCode(500).end(res.cause().stackTraceToString())
}
}
}
Vert.x for Kotlin provide a equivalent set of suspend functions. In your case you may want to implement the equivalent openAwait and pipeToAwait functions in order to avoid the "callback hell". Now your code might look like this:
router.post("/upload").handler { ctx ->
val startTime = System.currentTimeMillis()
val response = ctx.response()
val request = ctx.request()
val fs = vertx.fileSystem()
val asyncFile = fs.openAwait("data.bin", OpenOptions())
val result = request.pipeToAwait(asyncFile)
// code for sending http response
}
NSXMLParser Failed to parse data on watch but working fine on watch simulator.How to resolve this issue?
Kindly help
Here is Code:
let url:String="http://www.someurl.com/data"
let urlToSend: NSURL = NSURL(string: url)!
// Parse the XML
parser = NSXMLParser(contentsOfURL: urlToSend)!
parser.delegate = self
let success:Bool = parser.parse()
if success {
print("parse success!")
print(strXMLData)
} else {
print("parse failure!")
}
I've experienced the same issue, and I couldn't debug the app when running on the watch. My solution was to parse the XML file in the iPhone App side and communicate the data to the watch through a WCSession.
I had exactly the same problem. I found an answer on one of Apple's own forums.
You need to read in the XML from URL into NSData, then invoke XML parser with NSData object, not the NSURL.
Here is some code
var nsXMLData = NSData()
var parser = NSXMLParser()
func xmlFileRequest(urlweb:NSURL){
print("in xmlFileRequest")
let requestURL: NSURL = urlweb
let urlRequest: NSMutableURLRequest =
NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
if error == nil {
print(">>>>>>xmlFileRequest success!")
self.nsXMLData = data!
self.beginParsing()
} else {
print(">>>>>>>xmlFileRequest fail")
}
}
task.resume()
}
func beginParsing()
{
parser = NSXMLParser.init(data:nsXMLData)
parser.delegate = self
let success:Bool = parser.parse()
if success {
print("***parse success***")
} else {
print("***parse failure!***")
let errorMsg:String =
(parser.parserError?.localizedDescription)!
print("Error = " + errorMsg)
}
}
I just tested this code on our Apple watch.
I need to upload a zip file to a url that accepts files passed in a multipart request. The name of the part in the "multipart/form-data" request to bind to is "archive".
What I have so far:
auto f = new BufferedFile(<path_to_file>, FileMode.In);
scope (exit) f.close();
http = HTTP(<post_url>);
http.addRequestHeader("Content-Type", "multipart/form-data;boundary=heregoes");
http.verifyPeer(false);
http.method = HTTP.Method.post;
http.onSend = (void[] data){
return f.read(cast(ubyte[]) data);
};
http.contentLength = cast(size_t) f.size;
http.setCookieJar("<cookie_file_used_for_auth>");
http.perform();
How can I set the key "archive" in the request to map the file to?
Thanks
I don't use std.net.curl much so I don't know if there's an easier way, but the data you're sending is just a blob on the wire, so you could set the other values manually.
Don't just send the data, put it in a MIME envelope. I wrote this little class a while ago to help form that:
/// Creates a multipart/form-data object that is suitable for file uploads and other kinds of POST
class FormData {
struct MimePart {
string name;
const(void)[] data;
string contentType;
string filename;
}
MimePart[] parts;
void append(string key, in void[] value, string contentType = null, string filename = null) {
parts ~= MimePart(key, value, contentType, filename);
}
private string boundary = "0016e64be86203dd36047610926a"; // FIXME
ubyte[] toBytes() {
string data;
foreach(part; parts) {
data ~= "--" ~ boundary ~ "\r\n";
data ~= "Content-Disposition: form-data; name=\""~part.name~"\"";
if(part.filename !is null)
data ~= "; filename=\""~part.filename~"\"";
data ~= "\r\n";
if(part.contentType !is null)
data ~= "Content-Type: " ~ part.contentType ~ "\r\n";
data ~= "\r\n";
data ~= cast(string) part.data;
data ~= "\r\n";
}
data ~= "--" ~ boundary ~ "--\r\n";
return cast(ubyte[]) data;
}
}
I know that code sucks and I haven't tested it recently but the output eyeballs to be right. It should work like this:
auto data = new FormData();
data.append("archive", "YOUR DATA", "application/octet-stream"); // or whatever mime type you need
auto bytes = data.toBytes();
Then you send bytes instead of your file contents when curl asks for it. The setPostData method of HTTP looks like a place to put it. Remember to set your content type in the set post data too to the multipart/form-data with the boundary (you can change the one in my class if you like).
http://dlang.org/phobos/std_net_curl.html#setPostData
I know the curl library has functions to do this for you too... but I don't think the high level std.net.curl interface exposes them :(
I am new to the swift. Just couldn't get the below code working on the http request. Other than printing "start...", it doesn't print anything else. All the connection methods seem not called at all? Any suggestions?
class Network {
var data: NSMutableData = NSMutableData()
func getAcctSummary() {
let urlAcctSummary = "http://www.google.com"
var url: NSURL = NSURL(string: urlAcctSummary)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
connection.start()
println("started...")
}//getAcctSummary
func connection(connection: NSURLConnection!, didFailWithError error: NSError!) {
println("Failed with error:\(error.localizedDescription)")
}
func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
println("didReceiveResponse")
}
func connection(connection: NSURLConnection!, didReceiveData conData: NSData!) {
self.data.appendData(conData)
println("here 1")
}
func connectionDidFinishLoading(connection: NSURLConnection!) {
println(self.data)
println("here")
}
}
In order to determine which optional protocol methods are supported, the NSURLConnection delegate is required to be a subclass of NSObject. Change the first line to:
class Network : NSObject {
And you should be good-to-go
Try using swift NSURLSession. Worked best for me here is some ex code but had to pull out my custom code.
func someFunc() ->()
{
var session = NSURLSession.sharedSession()
var personURL = "URL"
let url = NSURL(string:personURL)
var task:NSURLSessionDataTask = session.dataTaskWithURL(url, completionHandler:apiHandler)
task.resume()
}
func apiHandler(data:NSData!, response:NSURLResponse!, error:NSError!)
{
if error
{
println("API error: \(error), \(error.userInfo)")
}
var jsonError:NSError?
var json:JMSMediaDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonError) as Dictionary
println(json)
//do stuff with data
}
Below code specifies that we we can make http connection in blackberry and how to store html page as a string?
I am doing this but I am able to get that http request but when I get response i.e http_ok it is not correct so that I can save text oh html as a string and I can further store that into sqlite.
LabelField title = new LabelField("SQLite Create Database Sample",
LabelField.ELLIPSIS |
LabelField.USE_ALL_WIDTH);
setTitle(title);
add(new RichTextField("Creating a database."));
argURL="https://www.google.com:80";
try {
connDesc = connFact.getConnection(argURL);
if (connDesc != null) {
httpConn = (HttpConnection) connDesc.getConnection();
// //Send Data on this connection
// httpConn.setRequestMethod(HttpConnection.GET);
// //Server Response
StringBuffer strBuffer = new StringBuffer();
inStream = httpConn.openInputStream();
int chr;
int retResponseCode = httpConn.getResponseCode();
if (retResponseCode == HttpConnection.HTTP_OK) {
if (inStream != null) {
while ((chr = inStream.read()) != -1) {
strBuffer.append((char) chr);
}
serverResponceStr = strBuffer.toString();
// appLe.alertForms.get_userWaitAlertForm().append("\n"+serverResponceStr);
//returnCode = gprsConstants.retCodeSuccess;
}
} else {
//returnCode = gprsConstants.retCodeNOK;
}
}
} catch (Exception excp) {
//returnCode = gprsConstants.retCodeDisconn;
excp.printStackTrace();
} `enter code here`
The code does not perform any database functionality, however I tested and it does successfully perform an HttpRequest to an external URL. The data that comes back is based on the response of the server you are making the request to.
The code I used can be found here:
http://snipt.org/vrl7
The only modifications is to keep a running summary of various events, and the response is displayed in the RichTextField. Basically, this looks to be working as intended, and the resulting String should be able to be saved however you see fit; though you may need to be cautious of encoding when saving to a database so that special characters are not lost or misinterpreted.