How to write functioning Webmock stubs with nested data? - webmock

I'm trying to write rspec tests. Some of them have to stub calls to external service.
Some of these calls send nested data, and this data never seems to be processed by Webmock correctly.
describe 'calc' do
before do
stub_request(:any, url).with(body: hash_including(operation: 'calc'))
end
it 'works' do
request_data = { sale_type: 'money', cover_type: 'money',
region: 'rf', period: 9,
adults: 600, children: 750, mice: 500 }
# This thing makes a HTTP request:
MiteService.new(login_params).calc(request_data)
expected_body = { operation: 'calc', product: 'mite3',
sessionID: session, data: request_data }
expect(WebMock).to have_requested(:post, url).with(body: expected_body)
end
end
This test is expected to pass. The http call made by service seems to be correct, but Webmock is unable to read any nested data (which is in data part of body in this case).
1) MiteService API calls calc works
Failure/Error: expect(WebMock).to have_requested(:post, url).with(body: expected_body)
The request POST http://example.com/api with body {"data"=>{"sale_type"=>"money", "cover_type"=>"money", "region"=>"rf", "period"=>9, "adults"=>600, "children"=>750, "mice"=>500}, "operation"=>"calc", "product"=>"mite3", "sessionID"=>"123"} was expected to execute 1 time but it executed 0 times
The following requests were made:
<...>
POST http://example.com/api with body 'operation=calc&product=mite3&sessionID=123&data=%7B%3Asale_type%3D%3E%22money%22%2C+%3Acover_type%3D%3E%22money%22%2C+%3Aregion%3D%3E%22rf%22%2C+%3Aperiod%3D%3E9%2C+%3Aadults%3D%3E600%2C+%3Achildren%3D%3E750%2C+%3Amice%3D%3E500%7D' with headers {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'Date'=>'Tue, 25 Dec 2018 08:20:32 GMT', 'User-Agent'=>'HTTPClient/1.0 (2.8.3, ruby 2.4.1 (2017-03-22))'} was made 1 time

Made it work for this example by converting fields into json in example spec.
expect(WebMock).to have_requested(:post, url).with(body: expected_body.to_json)

Related

vert.x request x-www-form-urlencoded array

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.

What does the BLE-status code "-402" mean?

I have a GarminIQ-project. Therefore I make a request. Since yesterday I get the error code -402.
According to https://developer.garmin.com/downloads/connect-iq/monkey-c/doc/Toybox/Communications/OAuthMessage.html#responseCode-instance_method negative values stand for BLE-responses, positive are the http-requestCode. Does anybody know what -402 stands for?
I am using the Connect IQ SDK 3.0.10.
I tried to find out, what the error code is meaning. But I haven't found a list with code "-402" or "402"
Down below are the two code snippets that are used for the request. The argument url is our api-url. This works fine in a browser.
//This function makes the request
function makeRequest(url) {
jsonFile = Communications.makeJsonRequest(url, {}, {}, method(:onReceive));
}
//This is the callback method that is called, when data have arrived
function onReceive(responseCode, data){
if (responseCode == 200) {
notify.invoke(1, data);
}else {
System.println(responseCode);
notify.invoke(0, "Failed to load\nError: "+responseCode.toString());
}
}
If you look at the API docs for the Communications module, you will see that -402 is the error code returned when the results sent back from your request were too large.
NETWORK_RESPONSE_TOO_LARGE = -402
Most devices have a very limited amount of memory and so you may need to run your request through some sort of proxy server to make the request and then trim down the results to only what you require back before sending the data to your device.

Elixir: HTTPResponseStream to consume streaming API

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.

Cross Domain AJAX Post using easyXdm

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)

Looks like Meteor.http.post is not working properly

I'm trying to post on a user's facebook feed from the server side of Meteor app:
result = Meteor.http.call 'POST',
"https://graph.facebook.com/#{facebook_id}/feed?access_token=#{app_access_token}",
{ data: { message: "some message", link: "http://www.somelink.com" } }
I got the following as a result:
{"statusCode":400,"content":"{\"error\":{\"message\":\"(#100) Missing message or attachment\",\"type\":\"OAuthException\",\"code\":100}}","headers":{"access-control-allow-origin":"*","cache-control":"no-store","content-type":"text/javascript; charset=UTF-8","expires":"Sat, 01 Jan 2000 00:00:00 GMT","pragma":"no-cache","www-authenticate":"OAuth \"Facebook Platform\" \"invalid_request\" \"(#100) Missing message or attachment\"","x-fb-rev":"710505","x-fb-debug":"doa24fNWaPsogxv4HmXa1/5KA30BBct86VZWVeYsins=","date":"Fri, 11 Jan 2013 13:57:52 GMT","connection":"keep-alive","content-length":"95"},"data":{"error":{"message":"(#100) Missing message or attachment","type":"OAuthException","code":100}},"error":{}}
I tried to reproduce this problem in Facebook debugger - I got the same message only if I do not send any parameters in POST body. Could it be the problem of POST implementation in Meteor.http.call?
You're sending your data in the HTTP POST request content body data, you need to use params to pass the correct variables on as postdata
try
result = Meteor.http.post(
"https://graph.facebook.com/#{facebook_id}/feed?access_token=#{app_access_token}",
{ params: { message: "some message", link: "http://www.somelink.com" } } );
Also if you're diong this in a Meteor.methods stub try using this.unblock(); so that other operations can occur simultaneously
Update: The newer versions of meteor use HTTP instead of Meteor.http, the code above would go as HTTP.post as a drop in replacement.

Resources