How to Parse (not get) an HTTP Request in Ruby - ruby

I have an integration test which uses eventmachine to receive http requests. This is my eventmachine handler:
class NotificationRecipient < EM::Connection
def receive_data(data)
EM.stop
end
end
I need to test various properies of the received request, e.g. I want to extract a json payload from an HTTP POST request string I've received like this. Is there a nicely packaged way to do it?
Googling finds lots of ways to make a request and parse the response, e.g. rest-client will parse response automatically. However, since I'm receiving the request, not making it, none of these ways work for me.

I would make use of WEBrick. WEBrick::HTTPRequest has a serviceable parser, and all you need to do is pass an IO object to its parse method and you have yourself an object you can manipulate.
This example declares a POST request with a JSON body in a string and uses StringIO to make it accessible as an IO object.
require 'webrick'
require 'stringio'
Request = <<-HTTP
POST /url/path HTTP/1.1
Host: my.hostname.com
Content-Type: application/json
Content-Length: 62
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}
HTTP
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
req.parse(StringIO.new(Request))
puts req.path
req.each { |head| puts "#{head}: #{req[head]}" }
puts req.body
output
/url/path
host: my.hostname.com
content-type: application/json
content-length: 62
{
"firstName": "John",
"lastName": "Smith",
"age": 25
}

Related

Send API get request from AWS Lambda in ruby

I was trying to send API request to my rails server from AWS Lambda function.
I was using httparty gem to send request.
I have tried with below code
require "httparty"
class PostManager
include HTTParty
def initialize
end
def create_post(job_id)
puts "----------------- Inside post manager ------------------"
puts "----------------- #{ENV["BASE_URI"]} ------------------"
puts "#{ENV['BASE_URI']}/call_response?job_id=#{job_id}"
response = HTTParty.get("#{ENV['BASE_URI']}")
puts "******************HTTP Response -: #{response}******************"
response
end
end
I am triggering this code from aws lambda main handler like below.
post_manager = PostManager.new
response = post_manager.create_post(job_id)
But lambda function gets timeout. Request not reaching to rails server at all.
Please guide me if i am missing something. Other alternatice to send post request to external server from aws lambda function is also invited.
Since http party is a http client, I recommend read the documentation, start experimenting with pry and a site like http://httpbin.org
So went will have all the thinks. reading your code I'm not sure of what you want to achieve, but I think that you want to connect to some en point that is on:
The domain inside this shell variable => #{ENV['BASE_URI']}
the path of the http method => call_response
and some path parameters like => job_id=#{job_id}
You allways say that this is a post but you are doing a get => HTTParty.get
So let's start with some object like the one showed in the documentation in order to attack to this method with curl will be something like this:
❯ curl -X GET "http://httpbin.org/get?job_id=4" -H "accept: application/json" ~/learn/ruby/stackoverflow
{
"args": {
"job_id": "4"
},
"headers": {
"Accept": "application/json",
"Host": "httpbin.org",
"User-Agent": "curl/7.64.1",
"X-Amzn-Trace-Id": "Root=1-613b73ef-2d00166a2ae40e704b448352"
},
"origin": "83.53.251.55",
"url": "http://httpbin.org/get?job_id=4"
}
Then for an http client object
add this to afile called httpbin_client.rb :
require 'httparty'
class HTTPbinClient
include HTTParty
base_uri ENV['BASE_URI']
def initialize
end
def ask_for_job_id(job_id)
self.class.get('/get', {query: {job_id: job_id}})
end
end
http_bin = HTTPbinClient.new
puts http_bin.ask_for_job_id(28)
call like this:
❯ BASE_URI=httpbin.org ruby httpbin_client.rb ~/learn/ruby/stackoverflow
{
"args": {
"job_id": "28"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
"Host": "httpbin.org",
"User-Agent": "Ruby",
"X-Amzn-Trace-Id": "Root=1-613b776d-47036b9b29bb1ae34b4a0e50"
},
"origin": "83.53.251.55",
"url": "http://httpbin.org/get?job_id=28"
}

how can I get list of email in gmail api with title and sender of email?

I have tried using
GET https://www.googleapis.com/gmail/v1/users/userId/messages
but only get id and threadId as a response.
I want to display list of email with title and from email. Is there an api exist to get info or any way I can get it?
Gmail API is designed in such a way, that
you need to obtain the IDs of all emails of interest (you can use the search parameter q to filter the results) with GET https://www.googleapis.com/gmail/v1/users/userId/messages - as you already did
you need to retrieve each of the messages separately by their ID with GET https://www.googleapis.com/gmail/v1/users/userId/messages/id
If you write a code in a language of your choice you can automatize this process with loops.
Sample how to do it with Apps Script:
function myFunction() {
var myMessages=Gmail.Users.Messages.list("me",{'maxResults': 5 }).messages;
Logger.log(myMessages);
for(var i=0;i<myMessages.length;i++){
var id=myMessages[i].id;
Gmail.Users.Messages.get('me', id).payload.headers.forEach(function(e){
if(e.name=="Subject"||e.name=="From"){
Logger.log(e.name+": "+e.value)
}
}
);
}
}
The user messages.list method only returns a message list of message id and thread id. This is a limitation in the API itself and there is nothing you can do to change that. Its a free api and we are bound by the limitations of google.
{
"messages": [
{
"id": "16d1f7849145662a",
"threadId": "16d1f55457d4e145"
},
{
"id": "16d1f69d541016ee",
"threadId": "16d1f55457d4e145"
},
In order to get additional information about the message you need to do a message.get on each message.
GET https://www.googleapis.com/gmail/v1/users/userId/messages/id
Sorry its the only way its a lot of gets.
batching
You can try the batching endpoing batch You're limited to 100 calls in a single batch request. If you need to make more calls than that, use multiple batch requests.
postman headers
Content-Type multipart/mixed; boundary=batch_foobarbaz; type=application/http
Authorization Bearer ya29.GluBB7_cEfLMThXKuxR_9g8YyjSTLwBHRHdPtiYXwDABKQlrbxEyFqSFsnFYTs5b54W7
Accept-Encoding application/gzip
postman body
--batch_foobarbaz
Content-Type: application/http
GET gmail/v1/users/me/messages/16d24956228a98c4
Accept: application/json; charset=UTF-8
--batch_foobarbaz
Content-Type: application/http
GET gmail/v1/users/me/messages/16d24956228a98c4
Accept: application/json; charset=UTF-8
--batch_foobarbaz--
SMTP
beyond that you can go though the smtp server directly. This will require a programming language which can handle direct calls to a mail server.

Why is Fiddler doing a GET when I set it to POST

When I try to call my WEB API from Fiddler it calls using GET even though I set Fiddler to use POST.
NOTE: All my GET API methods are working fine.
POST http://www.myapisite.com/api/UserAccounts/CreateAccount
[Header] User-Agent:
Fiddler Host: www.myapisite.com
Content-Type: application/json; charset=utf-8
Content-Length: 453
[Request Body]
{
"user_id": "1",
"store_id": "1",
"merchant_id": "1"
}
My WEB API method signature:
[ValidateModelState]
[System.Web.Mvc.HttpPost]
[Route("api/UserAccounts/CreateAccount")]
[EnableCors(origins: "mymvcsite.com", headers: "*", methods: "*")]
public virtual IHttpActionResult CreateAccont(
[FromBody]AccountHolderDto accountHolderDto)
{
...
}
AccountHolderDto is simply a class with public properties (user_id, store_id, merchant_id)
Any help much appreciated! - This has had me baffled the entire day
Damn!, I removed the "www" prefix of the uri and it works now
From this:
http://www.myapisite.com/api/UserAccounts/CreateAccount
To this:
http://myapisite.com/api/UserAccounts/CreateAccount
Unbelievable the smallest things cause so much pain

Parsing request JSON in Sinatra app

I am having some difficulty with parsing the JSON from a request to my Sinatra application:
response = JSON.pretty_generate(request.env)
reply = response["rack.request.form_hash"]
results in reply just returning:
rack.request.form_hash
as a string rather than just the relevant part of the response:
{...
"rack.request.form_hash": {
"token": "token",
"team_id": "team",
"team_domain": "teamname",
"service_id": "service",
"channel_id": "channel",
"channel_name": "testing-webhooks",
"timestamp": "1424480976.000910",
"user_id": "U029W1WF2",
"user_name": "myusername",
"text": "checkeverything",
"trigger_word": "checkeverything"
},
...}
which is within the JSON request object I'm trying to parse. When I use:
response["rack.request.form_hash"]["user_name"]
there is nothing returned. The following is returned in my log:
App 1662 stdout:
App 1640 stderr: JSON::ParserError - 746: unexpected token at 'No text specified':
So it looks like it's not iterating properly, or perhaps can't access it.
I've looked through other documentation and other posts, but found nothing that worked for me, but I am definitely overlooking something, but I'm not sure what.
What is the best way to parse this nested array in a request to Sinatra?
This should fix it :
res = JSON.parse( JSON.generate(request.env) )
res.class
# => Hash
res["rack.url_scheme"]
# => http
The reason is that the JSON.generate only generates JSON syntax for objects and arrays in a string. Then you need to parse the generated JSON string into a hash in Ruby with JSON.parse.

How to validate response with dredd?

I'm trying to check my api implementation with my documentation written in blueprint. I've expected that dredd will fail when json returned from server will be different than specified in documentation. To check this I've copied dredd-example. First I've run dredd with original apib file to make sure that all is green. Then I've modified response in documentation and expected dredd to show me some red... But it doesn't.... it looks like tool is only checking response headers but not the response body. Here is output from console:
pass: GET /machines duration: 18ms
request:
host: localhost
port: 3000
path: /machines
method: GET
headers:
User-Agent: Dredd/0.2.1 (Darwin 13.0.0; x64)
expected:
headers:
Content-Type: application/json
body:
[
{
"_id": "52341870ed55224b15ff07ef",
"type": "bulldozer",
"name": "willyxxxxxx" #HERE IS WHERE I CHANGED RESPONSE IN DOCUMENTATION
}
]
status: 200
actual:
headers:
x-powered-by: Express
content-type: application/json
content-length: 95
date: Thu, 20 Mar 2014 08:22:40 GMT
connection: keep-alive
body:
[
{
"_id": "532aa5507dcdfff362931799",
"type": "bulldozer",
"name": "willy"
}
]
status: 200
Can I check response body using dredd? And how can I do this?
In JSON bodies Dredd is checking only for keys not for values. When you change key in the expected JSON body document, it will definitely fails.

Resources