Sending JSON Webhook Response - json

I'm trying to receive a request from a webservice via JSON and send a successful response message back if the token is correct along with some other identifying information, otherwise send a proper error message
post "/hook/foo/bar" do
puts request.env
if request.env['TOKEN'] === "secret_code"
HTTParty.post("https://hook.com/hooks/catch/foo/bar/",
{
:body => #info.to_json,
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
})
[200, {}, "Success"]
else
[400, {}, "Authorization Failed"]
end
The service sending the hook (Zapier) says it sends successfully, but i'm not responding any meaningful data to them that I can use. I believe my formatting for my responses is wrong, but i'm not sure how.

David from the Zapier Platform team here.
Per the sinatra docs, you can return:
An Array with three elements: [status (Fixnum), headers (Hash), response body (responds to #each)]
So you're sending back no hints on the content type and a string as the body. This is valid, and your hook succeeds, but you can do better!
Zapier parses the response from an outgoing hook as JSON, so it's best to send that back.
I've just tested the following example:
require 'sinatra'
require 'json'
get '/' do
'hello world!'
end
post '/hook' do
{message: 'great!'}.to_json
end
and my response was parsed!
If you want to set a status code, honestly the easiest way to do it is with the function status(400) anytime before your return. That being said, a 401 is probably the code you want for Unauthorized", rather than400`. Either way though, zapier will flag that run as an error.
​Let me know if you've got any other questions!

Related

Text Response from Spring REST API endpoint, how to retrieve that on Angular Front end

Spring REST API is responding with following response:
On successful execution : It returns me a response of Text type.
On unsuccessful execution : It returns me JSON error object.
Front-End Service Class :
private detailsURL = 'http://localhost:8080/register';
constructor(private http:HttpClient){}
register(regisDetails): Observable<any>{
return this.http.post(this.detailsURL,regisDetails);
}
Front-End Component Class:
registerUser(){
this.service.register(this.regisForm.value).subscribe(
success => this.successMessage = success,
error => this.errorMessage = error.error.errorMessage
);
}
In case of error I'm getting the error message I'm supposed to get. But in case of success I'm not getting the successMessage.
Just wanted to know if there's any way to fetch the Text type response on front end. Or else I'll have to change my backend to send response of JSON Type for successful execution as well.
Please help me understand this thing.
You have to set the status for your response. In the controller part you have to mention consumes="application/json" in api request.
You should be doing your changes at the backend and provide the response in Json format response for both the success and backend. That would be the ideal solution.
It is really a bad design to provide a different response than what is expected. You could check the value of the header in request "accept:application/json" and provide response as was expected by the front end
Front End Fix :
However, in the front end you could always use
JSON.parse(success) to convert the text to Json object and use it further as required.

JSON is Malformed in Fetch POST request using React Native

I have a function in a React Native app that is supposed to send data to a server that I'm hosting. This function seems to be throwing errors though every time I press submit and this function is called. The function should be sending a POST request to my webserver and receive information back. It has no problem receiving information but sending is another story... The current code below is giving me an error that says "JSON Parse error: Unrecognized token '<'. But as you can see in my code below I do not even have that symbol present in the 2nd parameter of the fetch function. Occasionally, when I tweak what I have I get an error that also says 'JSON Parse error: Unexpected EOF'. I am not sure how exactly this request is I guess 'malformed'. I am pulling it straight from the docs given by Facebook. I have also tried Axiom & XMLHttpRequest and I am still seeing similar JSON errors. Anyone?
login = () => {
// check if the username is being passed off properly...
//alert(this.state.username);
fetch('MYURL', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
})
.then(function(response){ return response.json(); }) // transforms response into data that is readable for this app...
.then(function(data) {
console.log(data);
})
.done();
}
When I shoot that post request in Postman I get back header "Content-Type: text/html; charset=UTF-8". So you don't get json back at all, that's why it doesn't work. I would venture that you have to add the correct application/json header in your backend.

Express res.status(200).json(...) only sending json message. How to retrieve status code?

After a successful creation of new item in my database I send:
res.status(201).json({message:"Successfully Registered"});
On my angular front end I am able to console.log(res) and receive:
{message: "Successfully Registered"}
1) How do I get the status code on the front end? res.status returns undefined. The only response I'm getting is the JSON.
2) What would be the best way to confirm successful desired api calls? For example, when I log in and credentials are correct, should I check for a 200 and then proceed? Or send a custom JSON message and check if the message for example says "Successful login" then proceed?
A little bit late, but another option is to include the status in the JSON object:
res.status(201).json({message: "Successfully Registered", status: 201})
Now you can check the status in the front end doing res.status and use this to proceed with another action.
1- You can do res.status(200).send("You message here");
2- I would say your best option when doing the login and authenticating credentials is to create a session as such
req.session.user = req.body.username //username is the name attribute of the textfield
and then redirect to any page you'd like/you can also set status to 200
res.status(200);
I'm not familiar with Angular, but looking at the docs:
See https://angular.io/api/http/Response
You'll need to do something like:
http
.request('example.com')
.subscribe(response => console.log(response.status));
Sure, checking for 200 is fine. Typically with a REST API (inferred from what you've shown), after a login you're given back a JWT along with 200 OK. And any subsequent API all with that JWT will also yield a 200 OK along with the response body which is usually JSON.
You should tell your angular http client that you want to get the response status. By default, angular deserialize the response body, but you can set request option.observe:'response' to do so.
postData(model: MyModel): Observable<HttpResponse<{status: string}>> {
return this.http.post<{status: string}>(
model, { observe: 'response' });
}
See https://angular.io/guide/http#reading-the-full-response for details.
PS: sending a { status: 'message' } is not very useful, you may return an { id } or even nothing.
res.status(200).json({
status: 'success',
results: tours.length,
data:{
tour:tours
}
});
Usually, Jsend is a good choice to response, and also by convention. Absolutely you can see the 'status' in response data and the actually data you want in the data.
according to the angular guide, we can add observe in the options of our request.
getforgetpassword(email: string): Observable<any> {
const url = this.gatewayUrl + `newPasswordFor/${email}`;
return this.http.get(url, {observe: "response"});
}
using observe type as response will give total response along with request status, which you can use in your logic of controller.

Can't reply in the Slack thread making http post request with JSON

I want to reply in a slack thread via Slack API.
I have an object.
var msg = {
text: 'test',
thread_ts: '1513168789.000263' // it's right ts, I have checked
}
I make the request
request.post({
method: 'post',
body: msg,
json: true,
url: '<incoming slack webhook>'
})
I expect to get the message to be replied in a thread, but it's just posted in a channel.
You need to use chat.postMessage if you want to send messages to a thread. The incoming webhook will not work (or at least there is no information in the documentation that it would support it).
chat.postMessage has a property called thread_ts, which you can use to address the correct thread.
See also this answer about webhooks and threads.

getting csrf tokens for json post requests to a rails app

I have been playing around with using rest-client to access a rails app I have written. I've written a quick script to log in and make a post request. Everything is working but I did have to work round the fact that no authenticity_token is served if you make a request for a form in json. I had to make a regular html request in other get the authenticity_token and then included this in the json I submitted as part of my post request. Basically I have a quick an dirty script like the one below
private_resource = RestClient::Resource.new( 'https://mysite.com')
params = {:user => {:email => 'user#mysite.com', :password => 'please'}}
#log in
login_response = private_resource['users/sign_in'].post(params, :content_type => :json, :accept => :json)
#get cookie
cookie = login_response.cookies
#get json
json_response = private_resource['products/new'].get(:content_type => :json, :accept => :json, :cookies => cookie)
#another request that returns html form with authenticity token
response_with_token = private_resource['products/new'].get( :cookies => cookie)
#extract token
token = Nokogiri::XML(response_with_token).css('input[name=authenticity_token]').first.attr('value')
#update cookie
cookie = response_with_token.cookies
#populate form and insert token
form = JSON.parse(json_response)
form['name'] = "my product"
form['authenticity_token'] = token
#submit the request
private_resource['products'].post(form.to_json, {:cookies => cookie, :content_type => :json, :accept => :json})
There is the option to turn off CSRF protection for json requests but I would rather not do that. I could go the mechanize route or something similar and then I wouldn't worry about json requests with CSRF but I just wanted to play around with doing this stuff with rest-client
I guess I'm just curious to know if there is a reason why no authenticity_token is served for json requests and I'm also wondering if there is a better way of solving the token problem than the pretty hacky approach I've taken here
Put the below code into your application controller :
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
And call this method using before_filter .
For more details check :
http://blog.technopathllc.com/2011/09/rails-31-csrf-token-authenticity-for.html
And check this issue in rails : https://github.com/rails/rails/issues/3041
In your app/views/products/new.json.jbuilder, add this:
json.authenticity_token form_authenticity_token
This will insert a key "authenticity_token" with value being the token, so in your json_response you get the token as well. Idea from this answer.