How to send a Json in order to make an update in Rails? - ruby-on-rails-3

I am trying to make an update between flex and rails with something like this:
// TODO Auto-generated method stub
var strXml:XML = <test>
<test_id>{txtMarketId.text}</test_id>
<market_name>{txtMarketName.text}</market_name>
</test>;
req = new URLRequest("http://localhost:3000/tests/"+market_id);
jrwloader = new URLLoader();
params = new URLVariables();
req.data = strXml.toString();
req.method = URLRequestMethod.POST;
req.requestHeaders.push(new URLRequestHeader("X-HTTP-Method-Override", URLRequestMethod.PUT));
jrwloader.load(req);
In my rails app I got this:
Started PUT "/markets/2" for 10.10.10.10 at 2012-09-08 18:37:24 +0000
Processing by TestController#update as */*
Parameters: {"test_id:2, market_name:test"=>nil, "id"=>"2"}
WARNING: Can't verify CSRF token authenticity
Market Load (0.2ms) SELECT `tests`.* FROM `test` WHERE `test`.`test_id` = 2 LIMIT 1
(0.1ms) BEGIN
(0.1ms) COMMIT
Redirected to http://localhost:3000/tests/2
Completed 302 Found in 3ms (ActiveRecord: 0.4ms)
I think I am close to the answer but I cannot set the new data into the database.

You should add CSRF token to your request.
Here is more on the topic: http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf

I solve it! The main issue it was just to add one line in my request. So at the end I got something like this:
req = new URLRequest("http://localhost:3000/tests/"+market_id);
jrwloader = new URLLoader();
params = new URLVariables();
req.data = strXml.toString();
req.method = URLRequestMethod.POST;
req.requestHeaders.push(new URLRequestHeader("X-HTTP-Method-Override", URLRequestMethod.PUT));
**req.requestHeaders.push(new URLRequestHeader("Content-type", 'application/xml'));**         jrwloader.load(req);
thanks all!

Related

App-Only Token Fetches Users But Can't Create Subscriptions?

I am using an "app-only" token to retrieve my users which works just fine.
Once the app loops through the users, it's supposed to create a subscription as shown below.
However, when attempting to create the subscription, the request simply returns:
Code: InvalidRequest Message: Unable to connect to the remote server
Inner error
My question is, why does the subscription request fail to connect when I am obviously able to successfully connect in the first request which retrieves the users?
How can I see the inner error?
string tenantId = appSettings.TenantId;
var client = sdkHelper.GetAuthenticatedClientAppOnly(tenantId);
// this request works...
IGraphServiceUsersCollectionPage users = await client.Users.Request().Filter("userPrincipalName eq 'MY_USER_PRINCIPAL_NAME'").GetAsync();
if (users?.Count > 0)
{
foreach (User user in users)
{
// this request doesn't work...
Subscription newSubscription = new Subscription();
string clientState = Guid.NewGuid().ToString();
newSubscription = await client.Subscriptions.Request().AddAsync(new Subscription
{
Resource = $"users/{ user.Id }#{ tenantId }/mailFolders('Inbox')/messages",
//Resource = $"users/{ user.UserPrincipalName }/mailFolders('Inbox')/messages", // also tried using email address
ChangeType = "created",
NotificationUrl = "https://localhost:44334/notification/listen",
ClientState = clientState,
//ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0) // current maximum lifespan for messages
ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 15, 0) // shorter duration useful for testing
});
}
}
When I wrap the call in a try/catch, the error message is just this with no inner exception:
Exception of type 'Microsoft.Graph.ServiceException' was thrown.
I have tried all three resources URLs but all result in the same error as shown above:
Resource = $"users/{ user.Id }/mailFolders('Inbox')/messages",
Resource = $"users/{ user.Id }#{ tenantId }/mailFolders('Inbox')/messages",
Resource = $"users/{ user.UserPrincipalName }/mailFolders('Inbox')/messages",
I found this thread on github but the requests don't seem to work for me.
Allow Application-Only requests to create subscriptions - https://github.com/microsoftgraph/microsoft-graph-docs/issues/238
NotificationUrl cannot be "localhost!" The request is being sent from a remote server so it has no idea what localhost would be thus it fails. If I deploy my project to a remote server and pass the URL, it will likely work. I will try that...

Access-Control-Allow-Origin error on XMLHttpRequest

beginner here so please be gentle. For some time I've been trying to get a json file from the Walmart API using a XMLHttpRequest and always get that error:
XMLHttpRequest cannot load
http://api.walmartlabs.com/v1/items?apiKey={apikey}&upc=035000521019.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
I'm using an Apache server in which I have inserted the following code into the httpd.conf file , specifically to get rid of the Access-Control-Allow-Origin error. Still nothing.
LoadModule headers_module modules/mod_headers.so
and
<IfModule mod_headers.c>
# Accept cross-domain requests
Header always set Access-Control-Allow-Origin "*"
Please note that I will not give my API key here for obvious reasons, but while coding I inserted in the url the API key that Wal Mart gave me. The problem is not on the Wal Mart side because when I type the url in Chrome it get the text content of the JSON file. So... Here's my code, please help, I'm f#cking clueless.
function ajaxGet(url,callback){
req = new XMLHttpRequest();
req.open("GET", url);
req.addEventListener("load", function (){
if (req.status>=200 && req.status<400){
callback(req.responseText);
} else {
console.error("Erreur no." + req.status );
}
});
req.send(null);
}
function setHtml(texte){
var ouin = JSON.parse(texte);
var product = slashString(ouin.items[0].categoryPath);
var brand = ouin.items[0].brandName;
var price = ouin.items[0].salePrice;
document.getElementById("brand").innerHTML = brand;
document.getElementById("product").innerHTML = product;
document.getElementById("price").innerHTML = price;
}
function slashString(texte){
var n = texte.lastIndexOf("/");
var texte = texte.slice(n+1, texte.length);
return texte.toLowerCase();
}
ajaxGet("http://api.walmartlabs.com/v1/items?apiKey={apikey}&upc=035000521019",setHtml);

Using Twitter login API

I am trying to use https://api.periscope.tv/api/v2/loginTwitter to get a response from the server so that I can obtain a cookie for periscope API calls.
I have all of the required values for the request query, but I continue to get the "Bad Request" error (error code 400). Is anyone able to use the loginTwitter API still?
Request headers:
POST /api/v2/loginTwitter?bundle_id=com.bountylabs.periscope&phone_number=&session_key=xxxxxxxx&session_secret=xxxxxxxx&user_id=xxxxxxxx&user_name=xxxxxxxx&vendor_id=81EA8A9B-2950-40CD-9365-40535404DDE4 HTTP/1.1
Authorization:
OAuth oauth_consumer_key="xxxxxxxx",oauth_nonce="cecf203cda273c845cd5121007232666",oauth_signature="xxxxxxxx%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1474786616",oauth_token="xxxxxxxx",oauth_version="1.0"
Oauth signature:
POST&https%3A%2F%2Fapi.periscope.tv%2Fapi%2Fv2%2FloginTwitter%3Fbundle_id%3Dcom.bountylabs.periscope%26phone_number%3D%26session_key%xxxxxxxx%26session_secret%3xxxxxxxx%26user_id%3xxxxxxxx%26user_name%xxxxxxxx%26vendor_id%3D81EA8A9B-2950-40CD-9365-40535404DDE4&bundle_id%3Dcom.bountylabs.periscope%26oauth_consumer_key%3xxxxxxxx%26oauth_nonce%3Dcecf203cda273c845cd5121007232666%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1474786616%26oauth_token%xxxxxxxx%26oauth_version%3D1.0%26phone_number%3D%26session_key%xxxxxxxxMX%26session_secret%xxxxxxxxt%26user_id%xxxxxxxx4%26user_name%xxxxxxxx%26vendor_id%3D81EA8A9B-2950-40CD-9365-40535404DDE4
I have solved the problem thanks to help from another. The problem was that I was passing the request parameters in the URL without encoding them into json. For any that are looking to resolve this problem, here is the solution I arrived at with c#.
var httpWebRequest = ( HttpWebRequest )WebRequest.Create( "https://api.periscope.tv/api/v2/loginTwitter" );
httpWebRequest.ContentType = "application/json; charset=UTF-8";
httpWebRequest.Method = "POST";
using( var streamWriter = new StreamWriter( httpWebRequest.GetRequestStream() ) ){
string json = "{" +
"\"bundle_id\":\"com.bountylabs.periscope\"," +
"\"phone_number\":\"\"," +
"\"session_key\":\""+final_oauth_token+"\"," +
"\"session_secret\":\""+final_oauth_token_secret+"\"," +
"\"user_id\":\""+user_id+"\"," +
"\"user_name\":\""+screen_name+"\"," +
"\"vendor_id\":\"81EA8A9B-2950-40CD-9365-40535404DDE4\"" +
"}";
streamWriter.Write( json );
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = ( HttpWebResponse )httpWebRequest.GetResponse();
using( var streamReader = new StreamReader( httpResponse.GetResponseStream() ) ){
var result = streamReader.ReadToEnd();
display.Text = "cookie: "+result;
}
}
The result yields a cookie in the server's response.
Reference for more detail on this process: Twitter login POST request in Periscope API

How do I set http headers in Adobe Illustrator ExtendScript when using the BridgeTalk HttpConnection object?

I am trying to make http post requests from within Illustrator ExtendScript (via BridgeTalk) and for the most part it is working. However, the documentation on using HttpConnection is non-existent and I am trying to figure out how to set http-headers. The HttpConnection object has both a requestheaders and responseheaders property so I suspect it is possible.
By default, the post requests are being sent with the Content-Type header "text/html", and I would like to override it so that I can use either "application/x-www-form-urlencoded" or "multipart/form-data".
Here is what I have so far:
var http = function (callback) {
var bt = new BridgeTalk();
bt.target = 'bridge' ;
var s = '';
s += "if ( !ExternalObject.webaccesslib ) {\n";
s += " ExternalObject.webaccesslib = new ExternalObject('lib:webaccesslib');\n";
s += "}\n";
s += "var html = '';\n";
s += "var http = new HttpConnection('http://requestb.in/1mo0r1z1');\n";
s += "http.method = 'POST';\n";
s += "http.requestheaders = 'Content-Type, application/x-www-form-urlencoded'\n";
s += "http.request = 'abc=123&def=456';\n";
s += "var c=0,t='';for(var i in http){t+=(i+':'+http[i]+'***');c++;}t='BEFORE('+c+'):'+t;alert(t);\n"; // Debug: to see what properties and values exist on the http object
s += "http.response = html;\n";
s += "http.execute() ;\n";
s += "http.response;\n";
s += "var t='AFTER:';for(var i in http){t+=(i+':'+http[i]+'***');}alert(t);\n"; // Debug: to see what properties and values have been set after executing
bt.body = s;
bt.onResult = function (evt) {
callback(evt);
};
bt.onError = function (evt) {
callback(evt);
};
bt.send();
};
Things to note:
If I try setting the requestheaders properties like in my code above, the request fails. If I comment it out, the request succeeds. The default value for requestheaders is undefined.
Examining the http object after a successful request, shows the reponseheaders properties to be set to: "Connection, keep-alive,Content-Length, 2,Content-Type, text/html; charset=utf-8,Date, Wed, 24 Jun 2015 09:45:40 GMT,Server, gunicorn/18.0,Sponsored-By, https://www.runscope.com,Via, 1.1 vegur". Before the request executes, the responseheaders is set to undefined.
If anyone could help me set the request headers (in particular the Content-Type header), I would be eternally grateful!
Solved it!
The key for setting the content-type header is to set the http.mime property as follows:
s += "http.mime = 'application/x-www-form-urlencoded';\n";
Also for completeness, you can add your own custom headers as follows:
s += "http.requestheaders = ['My-Sample-Header', 'some-value'];\n";
(It turns out the headers is an array which takes the format [key1, value1, key2, value2, .......])

Set custom timeout in Net::HTTP::Get.new with Rails

I'm using this code to scraping external html files
link = URI.parse(url)
request = Net::HTTP::Get.new(link.path)
response = Net::HTTP.start(link.host, link.port) {|http|
http.request(request)
}
Works great but with slowed web pages sometimes responds timeout, so I need set a timeout limit per connection. Any idea?
You need to set the read_timeout attribute.
link = URI.parse(url)
request = Net::HTTP::Get.new(link.path)
begin
response = Net::HTTP.start(link.host, link.port) {|http|
http.read_timeout = 100 #Default is 60 seconds
http.request(request)
}
rescue Net::ReadTimeout => e
puts e.message
end