I have very little experience with APIs can someone please help me translate this:
$ curl -X POST -d "login_id=myemail#email.com&api_key=231421423423423423423" \
https://devapi.testapi.com/v2/authenticate/api
to something like this?:
include HTTParty
base_uri 'https://devapi.testapi.com'
def login
response = self.class.post( "/v2/authenticate/api",
:headers => { "login_id" => 'myemail#email.com', "api_key" => '231421423423423423423' }
).parsed_response
#token = response["auth_token"]
return #token
end
I'm not sure where to put login_id and api_key so that they would appear at the beginning of the request address instead of the end.
First, we need to clear up some confusion. When you send a POST request, like you did with Curl, it looks like this:
POST /v2/authenticate/api HTTP/1.1
User-Agent: curl/7.30.0
Host: localhost:8000
Accept: */*
Content-Length: 56
Content-Type: application/x-www-form-urlencoded
login_id=myemail#email.com&api_key=231421423423423423423
The first line is the request method (POST) and resource (/v2/authenticate/api) and the protocol version (HTTP/1.1). The next five lines are the headers, which always have a key (e.g. Content-Length), followed by a colon and space (:), followed by a value (56).
You'll notice that none of these headers have your data, i.e. login_id or api_key. Data doesn't go in the headers. It goes in the body, which is after the headers and an intervening blank line that tells the server, "the headers are done; everything else I send is the body."
Hopefully that will help clear up the confusion that I see here:
I'm not sure where to put login_id and api_key so that they would appear at the beginning of the request address instead of the end.
In a POST request the data is not part of the address, nor is it, to reiterate, part of the headers. It's the body.
When making a POST request with HTTParty, you could use the :body option to specify a string to use as the POST body, but in your Ruby code it looks like you'd rather use a Hash, which is the right way to go. With a Hash, you use the :query option instead of :body, and HTTParty will automatically encode the Hash's contents correctly. Using that, your code would look like this:
query_hash = { :login_id => 'myemail#email.com',
:api_key => '231421423423423423423' }
response = self.class.post("/v2/authenticate/api", :query => query_hash)
Related
I'm trying to write an API that delivers server-sent events using ActionController::Live::SSE in Rails 6. In order to understand how the tests would best be written, I started with essentially copying the trivial example seen here:
my_controller.rb:
class MyController < ApplicationController
include ActionController::Live
def capture
response.headers['Content-Type'] = 'text/event-stream'
sse = SSE.new(response.stream)
3.times do
sse.write({message: "Awaiting confirmation ..."})
sleep 2
end
fake_response = { #The response as hash.
"annotation_id"=>nil,
"domain"=>"some.random.com",
"id"=>2216354,
"path"=>"/flummoxer/",
"protocol"=>"https",
}
sse.write(fake_response, event: 'successful capture')
rescue => e
sse.write(e.message, event: 'something broke: ')
ensure
response.stream.close
end
end
When I send a curl request (whether I make it POST or GET) to this endpoint the response arrives all in one chunk, rather than as separate responses:
$ curl -i -X GET -H "Content-Type: application/json" -d '{"url": "https://some.random.com/flummoxer"}' http://localhost:3000/capture
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
ETag: W/"a24048695d2feca40232467f0fbb410a"
X-Request-Id: 648a5229-a43d-40d3-82fd-1c4ea6fe19cc
X-Runtime: 24.082528
Transfer-Encoding: chunked
data: {"message":"Awaiting confirmation ..."}
data: {"message":"Awaiting confirmation ..."}
data: {"message":"Awaiting confirmation ..."}
event: successful capture
data: {"annotation_id":null,"domain":"some.random.com","id":2216354,"path":"/flummoxer/","protocol":"https"}
This can more easily be seen by the fact that in my test, attempting to parse the response from my server fails:
MultiJson::ParseError: 783: unexpected token at 'data: {"message":"Awaiting confirmation ..."}
data: {"message":"Awaiting confirmation ..."}
data: {"message":"Awaiting confirmation ..."}
event: successful capture
data: {"annotation_id":null,"domain":"some.random.com","id":2216354,"path":"/flummoxer/","protocol":"https"}
'
My server is Puma, so it's not because I'm using Thin, as seen in this answer.
What am I doing wrong? I'll provide any additional information that might be of use, if you ask.
UPDATE: The answers to this question suggest adding both the -N and the Accept:text/event-stream header to the request. Doing so doesn't change the behavior I've described above -- the response to the request isn't sent until the call to response.stream.close is fired.
UPDATE 2: I've also tried hacking the SSE#write method to call broadcast() on the Mutex::ConditionVariable to force sending the message. This works, in the sense that it sends data immediately, but has the side effect of the curl request thinking that the stream is closed, and so no further messages are sent, which is not a stream.
UPDATE 3: I've also modified development.rb to include config.allow_concurrency = true, as seen here. There's no change in the behavior described above.
I ran into a similar issue with a basic 'out the book' Rails 5 SSE app. The issue turned out to be a Rack update that lead to buffering of the stream. More info here https://github.com/rack/rack/issues/1619 and fixed by including
config.middleware.delete Rack::ETag
in config/application.rb
I've got a line in my Varnish default.vcl that successfully clears the ChromePHP headers:
sub vcl_fetch {
remove beresp.http.X-ChromeLogger-Data;
}
I'm trying to do the same thing for FirePHP, but the data for FirePHP is spread out over many headers rather than all in one:
X-Wf-Protocol-1
X-Wf-1-Plugin-1
X-Wf-1-1-1-9
X-Wf-1-1-1-43
etc
How can I tell Varnish to remove any headers that start with "X-Wf-"? I can't find any documentation that includes a wildcard for the header name.
If you can, remove the x-wf-* request headers which will cause the response headers not to be issued. You can hardcode the names of the few request headers.
I have a problem with my app that reads e-mails from external server using mailman gem (which is also using mail).
ruby 1.9.2p0
mail (2.3.0)
mailman (0.4.0)
actionmailer (= 3.1.3)
database.yml
production:
adapter: mysql2
encoding: utf8
Here is a simple method to receive 'mail'. I build #message_body from text_part of multipart email (for ex. with attachments) or from the whole body (decoded).
def self.receive_mail(message)
# some code here
#message_body = message.multipart? ? message.text_part.body.to_s : message.body.decoded
# some code here, to save message in database
My problem is that if the message doesn't have attachments but have diacritics, like ą ś ł ń ż ź ó ... body is split just before first diacricit.
So if body is:
"test żłóbek test"
I will get only "test " in #message_body.
My question is how to save such a message in an elegant way, so that text part is saved in database with all diacritics.
EDIT:
to make it cleaner, I get e-mails that look like this one (it's just a part of e-mail sent from gmail)
--20cf307ac4372d830104c11c8cc6
Date: Mon, 28 May 2012 20:06:16 +0200
Mime-Version: 1.0
Content-Type: text/plain;
charset=ISO-8859-2
Content-Transfer-Encoding: base64
Content-ID: <4fc3be989b76e_794650c25f6625e3#vk1057.some_domain>
dGVzdCC/s7zm8bbzsSB0ZXN0Cg==
So we have this 'body' : dGVzdCC/s7zm8bbzsSB0ZXN0Cg==
After decoding we get : 'test \xbf\xb3\xbc\xe6\xf1\xb6\xf3\xb1 test\n'
And the problem is that starting from '\xbf' data is not saved in database.
UPDATE
another example, I think this is the problem here:
irb(main):008:0* require 'base64'
=> true
irb(main):009:0> a = "test źćłżąńś"
=> "test źćłżąńś"
irb(main):010:0> b = Base64.encode64(a)
=> "dGVzdCDFusSHxYLFvMSFxYTFmw==\n"
irb(main):011:0> Base64.decode64(b)
=> "test \xC5\xBA\xC4\x87\xC5\x82\xC5\xBC\xC4\x85\xC5\x84\xC5\x9B"
see, after decode64 my diacritics are LOST, what to do to get them back?
force_encoding('utf-8')
Doesn't work because the data isn't utf-8 - your mail headers clearly states that the message body is ISO 8859-2.
Mysql2 assumes everything is utf8 but can't convert the bytes to utf8 (because ruby doesn't know the original encoding) so your non ascii characters are thrown away by mysql
For that one string you could try
body.force_encoding('ISO-8859-2').encode('utf-8')
But really you want to be working out what encoding to use from the content type header. I'm surprised the mail gem isn't doing that for you
I have the solution. Concatenation of
.force_encoding("ORIGINAL_CHARSET").encode("UTF-8")
methods on E-Mail body object is the solution.
I had to change my receive_mail() definition from previous 'one liner' to:
if message.multipart?
charset = message.text_part.content_type_parameters[:charset]
#message_body = message.text_part.body.to_s.force_encoding(charset).encode("UTF-8")
else
charset = message.content_type_parameters[:charset]
#message_body = message.body.decoded.force_encoding(charset).encode("UTF-8")
end
With this construct I can detect what was the charset of original e-mail and then force it and encode back to UTF-8. This ensures proper decoding from base64 from original to utf-8.
If anyone has more elegant solution, please share.
I'm try to add binary file data directly to the request body of a POST call so I can simulate a file upload. However, I tried setting a 'before request' breakpoint and using 'insert file' but I couldn't seem to get that to work. I also tried to modify CustomRules.js to inject the file but couldn't figure out how to load binary data via JScript. Is there an easy solution here?
I'm sure this is a new feature in the year since this question was answered, but thought I'd add it anyhow:
There's a blue "[Upload file]" link in Composer now on the right side under the URL textbox. This will create a full multipart/form-data request. If you use this, you'll notice in the body you now have something that looks like this:
<#INCLUDE C:\Some\Path\my-image.jpg#>
In my case, I just wanted to POST the binary file directly with no multipart junk, so I just put the <#INCLUDE ... #> magic in the request body, and that sends the binary file as the body.
In order to send multipart/form-data, this receipe will be helped.
In upper panel (Http header), set Content-Type as below. Other values are automatically resolved.
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
And, input Response Body at the below panel as follows.
---------------------------acebdf13572468
Content-Disposition: form-data; name="description"
the_text_is_here
---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="123.jpg"
Content-Type: image/jpg
<#INCLUDE *C:\Users\Me\Pictures\95111c18-e969-440c-81bf-2579f29b3564.jpg*#>
---------------------------acebdf13572468--
The import rules are,
Content-Type should have two more - signs than boundary words in body.
The last of the body should be ended with two - signs.
In Fiddler script: (in Fiddler: Rules... Customize Rules), find the OnBeforeRequest function, and add a line similar to:
if (oSession.uriContains("yourdomain"))
{
oSession.LoadRequestBodyFromFile("c:\\temp\\binarycontent.dat");
}
since version 2.0, the Request Body has an "Upload File..." link that allows you to post/upload binary data.
I'm working on a homework assignment in Perl CGI using the CGI.pm module. In my code I am checking for a cookie. If the cookie exists, I want to initiate another CGI script. In other situations I was able to use similar code, but in this instance I merely get the following browser output, not the redirect that I was looking for.
Refresh: 1; URL=homepage.pl.cgi
Content-Type: text/html; charset=ISO-8859-1
Here's my code:
#get the cookie
my %SIDhash = cookie('SIDhash');
if ( exists $SIDhash{"SID"} ) {
print header(-refresh=>'0; homepage.pl.cgi');
}
What fundamentals am I not understanding here?
Thanks,
CB
This should do the trick:
print header(
-refresh => '0; url=homepage.pl.cgi',
-cookie => $cookie,
);
If you are assembling the header in pieces, in various places in your code, save the header components in a variable first, e.g.:
my %headers;
# later...
$headers{-cookie} = $cookie;
# later still:
if (exists $SIDhash{SID})
{
# we want to redirect, so print all headers and we're done.
print header(%headers, -refresh => '0; url=homepage.pl.cgi');
exit;
}
# if we're still here, nothing is printed yet.. continue preparing data and print when ready.
# ...
I'm not sure why your refresh doesn't work, but it sounds like it would be more appropriate to use:
HTTP/1.1 302 Found
Location: http://www.example.org/
Just a thought.
Try changing the line to
print header(-refresh=>'0; url=homepage.pl.cgi');
From what I can tell, this should be correct now.
This page on Wikipedia offers information on Refresh and other methods of redirection.