Good day.
I want to make a web service for processing an HTTP request. The request has:
Content-Type: x-www-form-urlencoded and body: Name=Vasya&Email=main#mail.ru&Phone=49494994&payment[sys]=none&payment[systranid]=0&payment[orderid]=1133704863&payment[products][0][name]=Мороженко&payment[products][0][quantity]=1&payment[products][0][amount]=4566&payment[products][0][price]=4566&payment[products][0][sku]=4345345345&payment[products][1][name]=Стаканчик&payment[products][1][quantity]=1&payment[products][1][amount]=100&payment[products][1][price]=100&payment[products][1][sku]=59595959&payment[amount]=4666&formid=form218781270&formname=Cart
I can't get payment parameters (payment{}).
I use: routingContext.request().getParam("Phone") but for payment this approach does not work.
Please help with advice
Form data is plain flat key-value.
I created a little example server code based on your description:
suspend fun main() {
val vertx = Vertx.vertx()
val router = Router.router(vertx)
router.route()
.handler(BodyHandler.create())
router.post("/test")
.handler { ctx ->
ctx.request().formAttributes().forEach {
println("${it.key}: ${it.value}")
}
ctx.response().end()
}
vertx.createHttpServer()
.requestHandler(router)
.listenAwait(8080)
}
Running it with your body, this is the key value pairs in the map:
Name: Vasya
Email: main#mail.ru
Phone: 49494994
payment[sys]: none
payment[systranid]: 0
payment[orderid]: 1133704863
payment[products][0][name]: Мороженко
payment[products][0][quantity]: 1
payment[products][0][amount]: 4566
payment[products][0][price]: 4566
payment[products][0][sku]: 4345345345
payment[products][1][name]: Стаканчик
payment[products][1][quantity]: 1
payment[products][1][amount]: 100
payment[products][1][price]: 100
payment[products][1][sku]: 59595959
payment[amount]: 4666
formid: form218781270
formname: Cart
As you can see, there is no Payment key.
I suggest that you use JSON (application/json) for your server and client and not form-data, it will be simpler and better suited for your use-case.
If not, you can try to iterate the attributes and extract what you need from the form data.
Related
Hello I need help with http post request to my server and get response with authentication.
Look on the screens on 1 I use insomnia REST API application. Using this app I got success response with premium days and id.
In second image I got response just from my nativescript vue.js app where I got false response.
There is something wrong with my code. please tell me what.
You are sending a JSON object in your request body from {N} app, on the other hand you are using FormData with your REST client for testing.
You must either change your API to support JSON data on request body which is generally the standard way. In case if you can't do that, then you must use the nativescript-background-http plugin to send FormData. It will be something like,
var params = [
{ name: "username", value: "test" },
{ name: "password", value: "test123" },
{ name: "uuid", value: "xxxx" }
];
var task = session.multipartUpload(params, request);
I want to write a client which can consume streaming APIs. Essentially, have a getter that returns an HTTPResponseStream instead of HTTPResponse. I couldn't find one in HTTPotion, so I figured I'd give it a try instead. But I have no idea how to go about it, and would really appreciate some help!
You can do async requests with HTTPotion like so:
%HTTPotion.AsyncResponse{ id: id } = HTTPotion.get "http://example.com", [], [stream_to: self]
This will send messages of three different types to the current process (which is defined above via self):
# First, the response headers
%HTTPotion.AsyncHeaders{ id: ^id, status_code: 200, headers: _headers }
# Then, one or more chunks
%HTTPotion.AsyncChunk{ id: ^id, chunk: _chunk }
# And finally, an end message
%HTTPotion.AsyncEnd{ id: ^id }
The id can be used to handle the responses from multiple ongoing requests.
Currently, I use the built-in meteor http method (see http://docs.meteor.com/#http) for issuing http calls, on both my client and my server.
However, I'm experiencing two issues:
is it possible to cancel a request?
is it possible to have multiple query parameters which share the same key?
Are these just Meteor limitations, or are there ways to get both to work using Meteor?
I know I could you jquery on the clientside, and there must be a server-side solution which supports both as wel, but I'd prefer sticking with meteor code here.
"is it possible to cancel a request?"
HTTP.call() does not appear to return an object on which we could call something like a stop() method. Perhaps a solution would be to prevent execution of your callback based on a Session variable?
HTTP.call("GET", url, function(error, result) {
if (!Session.get("stopHTTP")) {
// Callback code here
}
});
Then when you reach a point where you want to cancel the request, do this:
Session.set("stopHTTP", true);
On the server, instead of Session perhaps you could use an environment variable?
Note that the HTTP.call() options object does accept a timeout key, so if you're just worried about the request never timing out, you can set this to whatever millisecond integer you want.
"is it possible to have multiple query parameters which share the same key?"
Yes, this appears to be possible. Here's a simple test I used:
Meteor code:
HTTP.call("GET", "http://localhost:1337", {
query: "id=foo&id=bar"
}, function(error, result) {
// ...
});
Separate Node.js server: (just the basic example on the Node.js homepage, with a console.log line to output the request URL with query string)
var http = require('http');
http.createServer(function(req, res) {
console.log(req.url); // Here I log the request URL, with the query string
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
When the Meteor server is run, the Node.js server logged:
/?id=foo&id=bar
Of course, this is only for GET URL query parameters. If you need to do this for POST params, perhaps you could store the separate values as a serialized array string with EJSON.stringify?
I am trying to get a cross domain AJAX post to work using the easyXdm library.
In my local development environment I have two sites:
1. http://localhost/MySite/ws/easyXDM/cors/index.html (EasyXdm file)
2. http://localhost/MyClientSite/TestPage.html (AJAX post from here)
TestPage.html (AJAX Post)
var rpc = new easyXDM.Rpc({
remote: "http://localhost/MySite/ws/easyXDM/cors/index.html"
},
{
remote: {
request: {}
}
});
rpc.request({
url: "http://localhost/MySite/ws/MyService.asmx/DoSomething",
method: "POST",
data: jsonData
}, function(response) {
console.log(JSON.parse(response.data));
$('#thanksDiv').fadeIn(2000, function () {
$('#thanksDiv').fadeOut(4000);
});
});
When I do the AJAX post I get the following in my browser's console:
easyXDM present on 'http://localhost/MySite/ws/easyXDM/cors/index.html?xdm_e=http%3A%2F%2Flocalhost%2FMyClientSite%2FTestPage.html&xdm_c=default884&xdm_p=4
native JSON found
easyXDM.Rpc: constructor
{Private}: preparing transport stack
{Private}: using parameters from query
easyXDM.stack.SameOriginTransport: constructor
easyXDM.stack.QueueBehavior: constructor
easyXDM.stack.RpcBehavior: init
{Private}: firing dom_onReady
... deferred messages ...
easyXDM.Rpc: constructor
{Private}: preparing transport stack
{Private}: using parameters from query
easyXDM.stack.SameOriginTransport: constructor
easyXDM.stack.QueueBehavior: constructor
easyXDM.stack.RpcBehavior: init
... end of deferred messages ...
easyXDM.stack.SameOriginTransport: init
easyXDM.stack.RpcBehavior: received request to execute method request using callback id 1
easyXDM.stack.RpcBehavior: requested to execute procedure request
easyXDM.stack.QueueBehavior: removing myself from the stack
Problem: The web service never actually receives the data. This is obvious as my AJAX post success function should show a thanksDiv and also a record should be created in the *database.
Note: I am replacing my existing AJAX post code as I need to use easyXdm to overcome an issue with Internet Explorer 6 and 7 on a client's site.
Additional Information:
The file-structure where my easyXdm files are located is as follows:
/ws/easyXDM/easyXDM.debug.js
/ws/easyXDM/easyXdm.swf
/ws/easyXDM/json2.js
/ws/easyXDM/name.html
/ws/easyXDM/cors/index.html
My web service was throwing a HTTP 500 server error as jsonData was not being sent correctly via easyXdm.
The json data looks like this before it was posted:
{ "param1": "value1", "param2": "value2"...... }
However, the web service was receiving the data one character per line e.g.
{
"
p
a
r
a
m
"
....
I was not serialising the json data prior to my post. So, based on the original code I posted in the original question:
To get it working I changed the line
data: jsonData
to
data: JSON.parse(jsonData)
I am building a registration form (passport-local as authentication, forms as form helper).
Because the registration only knows GET and POST I would like to do the whole handling in one function.
With other words I am searching after something like:
exports.register = function(req, res){
if (req.isPost) {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
The answer was quite easy
exports.register = function(req, res) {
if (req.method == "POST") {
// do form handling
}
res.render('user/registration.html.swig', { form: form.toHTML() });
};
But I searched a long time for this approach in the express guide.
Finally the node documentation has such detailed information:
http://nodejs.org/api/http.html#http_http_request_options_callback
Now you can use a package in npm => "method-override", which provides a middle-ware layer that overrides the "req.method" property.
Basically your client can send a POST request with a modified "req.method", something like /registration/passportID?_method=PUT.
The
?_method=XXXXX
portion is for the middle-ware to identify that this is an undercover PUT request.
The flow is that the client sends a POST req with data to your server side, and the middle-ware translates the req and run the corresponding "app.put..." route.
I think this is a way of compromise. For more info: method-override