I'm trying to set up an automatic tumblr post every time I add something new to my website. I'm using the following code:
$conskey = "APIKEY";
$conssec = "APISECRET";
$tumblr_blog = "blogname.tumblr.com";
$to_be_posted = "This is the text to be posted";
$oauth = new OAuth($conskey,$conssec);
$oauth->fetch("http://api.tumblr.com/v2/blog/".$tumblr_blog."/post", array('type'=>'text', 'body'=>$to_be_posted), OAUTH_HTTP_METHOD_POST);
$result = json_decode($oauth->getLastResponse());
if($result->meta->status == 200){
echo 'Success!';
}
As far as I can tell this is all formatted correctly. However this is the first time I've tried to connect up to a JSON API using Oauth so I'm not totally confident in what I'm doing.
This is the exact error I'm receiving:
Fatal error: Uncaught exception 'OAuthException' with message 'Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)' in /home/public_html/edge/tumblr.php:35 Stack trace: #0 /home/public_html/edge/tumblr.php(35): OAuth->fetch('http://api.tumb...', Array, 'POST') #1 /home/public_html/edge/index.php(95): include('/home/...') #2 {main} thrown in /home/public_html/edge/tumblr.php on line 35
Line 35 is the line beginning with $oauth->fetch.
Thanks for any help :-)
EDIT
I've solved the issue by substituting my previous code with the example on this page
Related
I'm working in VFP9 sending data (in json format) to an api restfull using MSXML2.XMLHTTP.
I need to know if is possible to get the full json text that is sent. At this moment I only can get the data who is send with the "send" method. I need to see the complete json text, with the headers, data, etc. Is this possible?
Thanks in advance.
Alejandro
I use Microsoft.XMLHttp for REST API calls and works fine for me. Don't know if there would be any difference with MSXML2.XMLHTTP though.
First, here is a REST API test code (testing on typeicode.com):
clear
Local loXmlHttp As "Microsoft.XMLHTTP", lcUrl, postData,userID,id,title,body
*** We want to make this REST API call to typicode.com online test service:
***
*** https://jsonplaceholder.typicode.com/posts
*** with parameters payload
***
*** userId:12
*** title:From VFP
*** body:This is posted from VFP as a test
***
*** We do a POST call and want to 'create' a resource (insert call)
userID=12
title="From VFP"
body = "This is posted from VFP as a test"
Text to postData textmerge noshow
{
"userId":<< m.userID >>,
"title":"<< m.title >>",
"body": "<< m.body >>"
}
endtext
lcUrl = 'https://jsonplaceholder.typicode.com'
loXmlHttp = Newobject( "Microsoft.XMLHTTP" )
loXmlHttp.Open( "POST" , m.lcUrl + '/posts', .F. )
loXmlHttp.setRequestHeader("Content-Type","application/json; charset=UTF-8")
loXmlHttp.Send( m.postData )
*** Print the URL we are sending our POST REST request
? m.lcUrl + '/posts'
? "==================================="
? "Post Test", loXmlHttp.Status
? loXmlHttp.responsetext
? "==================================="
*** We get the response code back with loXmlHttp.Status
*** Since we made a POST call to create a resource, on succesful call
*** we expect an 201-Created code back
*** We also print out the full JSON response from the call
*** Which looks like:
***
*** {
*** "userId": 12,
*** "title": "From VFP",
*** "body": "This is posted from VFP as a test",
*** "id": 101
*** }
***
*** Next line simply has a MessageBox to allow you to see the results
*** of the above call before continuing. It also reminds,
*** 200 is the OK and 201 is the Created response code.
MessageBox("Continue? API Codes: 200-OK, 201-Created",0,"REST API Test",10000)
*** Then we try a new call to REST API with a GET call
*** asking to GET the post with id=3
*** If you have checked the typicode.com page there are some data there for testing:
***
***
*** /posts 100 posts
*** /comments 500 comments
*** /albums 100 albums
*** /photos 5000 photos
*** /todos 200 todos
*** /users 10 users
***
*** In our first call we ask for /posts/3
*** You could also go to this link in your browser to get the response back:
*** https://jsonplaceholder.typicode.com/posts/3
***
clear
m.id = 3
loXmlHttp.Open( "GET" , Textmerge('<< m.lcUrl >>/posts/<< m.id >>'), .F. )
loXmlHttp.Send( )
? "Get post with ID X test", loXmlHttp.Status
? loXmlHttp.responsetext
? "==================================="
*** Again we have a MessageBox to allow you to see the results
*** of the above call before continuing.
MessageBox("Continue? API Codes: 200-OK, 201-Created",0,"REST API Test",10000)
clear
*** Finally we try another GET call to REST API
*** asking to GET the comments done for the id=3
***
*** You could also go to this link in your browser to get the response back:
*** https://jsonplaceholder.typicode.com/posts/3/comments
***
loXmlHttp.Open( "GET" , Textmerge('<< m.lcUrl >>/posts/<< m.id >>/comments'), .F. )
loXmlHttp.Send( )
? "Get test post X comments", loXmlHttp.Status
? loXmlHttp.responsetext
? "==================================="
MessageBox("Continue? API Codes: 200-OK, 201-Created",0,"REST API Test",10000)
clear
*** Let's add another final request in this sample
*** to GET, posts done by the user whose userId is 2
userId = 2
loXmlHttp = Newobject( "Microsoft.XMLHTTP" )
loXmlHttp.Open( "GET" , m.lcUrl + '/posts?userId=2', .F. )
loXmlHttp.Open( "GET" , Textmerge('<< m.lcUrl >>/posts?userId=<< m.userId >>'), .F. )
loXmlHttp.Send( )
? "==================================="
? "GET posts of user X's Test", loXmlHttp.Status
? loXmlHttp.responsetext
? "==================================="
To check what you are really sending, you can use tools like postman or ngrok. I will use ngrok here as it is simple. You can use it for free. Download and then at command prompt:
ngrok http 80
80 is default http port, you might choose say 8080, too. It would start a tunnel and on screen sho you the address, and also a web interface address, likely:
http://127.0.0.1:4040
In your browser, go to that adress. In VFP, change your URL for testing and run. ie: We would test the first call in the above sample like this (the address would be different for you, grab it from ngrok's web interface that you opened in browser):
clear
Local loXmlHttp As "Microsoft.XMLHTTP", lcUrl, postData,userID,id,title,body
userID=12
title="From VFP"
body = "This is posted from VFP as a test"
Text to postData textmerge noshow
{
"userId":<< m.userID >>,
"title":"<< m.title >>",
"body": "<< m.body >>"
}
endtext
lcUrl = 'http://30dd0443adff.eu.ngrok.io'
loXmlHttp = Newobject( "Microsoft.XMLHTTP" )
loXmlHttp.Open( "POST" , m.lcUrl + '/posts', .F. )
loXmlHttp.setRequestHeader("Content-Type","application/json; charset=UTF-8")
loXmlHttp.Send( m.postData )
and run it. In ngrok web interface you would see the POST request done. Clicking it you would see details on right, summary, headers, RAW, ... tabs.
If you downloaded and use Postman (it is really great for working on REST API), you could create a POST request there and send, check response, get code in various languages etc but explaining it here is not as easy as the above ngrok. You should however check it if you would work with REST API and it takes 5 mins to start understanding making requests there.
I am trying to parse a json payload sent via a POST request to a NGINX/Openresty location. To do so, I combined Openresty's content_by_lua_block with its cjson module like this:
# other locations above
location /test {
content_by_lua_block {
ngx.req.read_body()
local data_string = ngx.req.get_body_data()
local cjson = require "cjson.safe"
local json = cjson.decode(data_string)
local endpoint_name = json['endpoint']['name']
local payload = json['payload']
local source_address = json['source_address']
local submit_date = json['submit_date']
ngx.say('Parsed')
}
}
Parsing sample data containing all required fields works as expected. A correct JSON object could look like this:
{
"payload": "the payload here",
"submit_date": "2018-08-17 16:31:51",
},
"endpoint": {
"name": "name of the endpoint here"
},
"source_address": "source address here",
}
However, a user might POST a differently formatted JSON object to the location. Assume a simple JSON document like
{
"username": "JohnDoe",
"password": "password123"
}
not containing the desired fields/keys.
According to the cjson module docs, using cjson (without its safe mode) will raise an error if invalid data is encountered. To prevent any errors being raised, I decided to use its safe mode by importing cjson.safe. This should return nil for invalid data and provide the error message instead of raising the error:
The cjson module will throw an error during JSON conversion if any invalid data is encountered. [...]
The cjson.safe module behaves identically to the cjson module, except when errors are encountered during JSON conversion. On error, the cjson_safe.encode and cjson_safe.decode functions will return nil followed by the error message.
However, I do not encounter any different error handling behavior in my case and the following traceback is shown in Openresty's error.log file:
2021/04/30 20:33:16 [error] 6176#6176: *176 lua entry thread aborted: runtime error: content_by_lua(samplesite:50):16: attempt to index field 'endpoint' (a nil value)
Which in turn results in an Internal Server Error:
<html>
<head><title>500 Internal Server Error</title></head>
<body>
<center><h1>500 Internal Server Error</h1></center>
<hr><center>openresty</center>
</body>
</html>
I think a workaround might be writing a dedicated function for parsing the JSON data and calling it with pcall() to catch any errors. However, this would make the safe mode kind of useless. What am I missing here?
Your “simple JSON document” is a valid JSON document. The error you are facing is not related to cjson, it's a standard Lua error:
resty -e 'local t = {foo = 1}; print(t["foo"]); print(t["foo"]["bar"])'
1
ERROR: (command line -e):1: attempt to index field 'foo' (a number value)
stack traceback:
...
“Safeness” of cjson.safe is about parsing of malformed documents:
cjson module raises an error:
resty -e 'print(require("cjson").decode("[1, 2, 3"))'
ERROR: (command line -e):1: Expected comma or array end but found T_END at character 9
stack traceback:
...
cjson.safe returns nil and an error message:
resty -e 'print(require("cjson.safe").decode("[1, 2, 3"))'
nilExpected comma or array end but found T_END at character 9
I can't seem to catch an exception when using json.loads even though I specifically call it out. I largely see this when trying to stress my server with lots of client connection sending data very quickly. See my error below:
(I've replaced my IP address with X's in the error code)
EX: Unterminated string starting at: line 1 column 49 (char 48) Data:
'{"ap-hdop":0.55,"rtcmin":"38","ap-latdec":3.134,"a' error: uncaptured
python exception, closing channel
(:Unterminated string
starting at: line 1 column 49 (char 48)
[//faraday_server_handler.py|collect_incoming_data|34]
[/usr/lib/python2.7/json/init.py|loads|338]
[/usr/lib/python2.7/json/decoder.py|decode|366]
[/usr/lib/python2.7/json/decoder.py|raw_decode|382])
I understand this that the code fails because I simply miss a double quotes on the line:
'{"ap-hdop":0.55,"rtcmin":"38","ap-latdec":3.134,"a'
This line is usually a LOT longer so that "a.... was supposed to keep going and complete it's quotes.
Here's my relevant code:
def collect_incoming_data(self, data):
"""Read an incoming message from the client, place JSON message data into buffer"""
#self.logger.debug('collect_fing_data() -> (%d bytes)\n"""%s"""', len(data), data)
try:
loaded_data = json.loads(data)
except ValueError, ex:
self.handle_error()
type,value,traceback = sys.exc_info()
print type
#print "Collect Incoming Data: " . time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())
print "EX: ", ex
print "Data: ",repr(data)
Any ideas? I scoured the internet to see if I can find this issue, but I appear to be setting up to capture the exception which everyone else having this issue with loads seems to suggest to do.
EDIT 3/1/2016 - Evening
Commenting out my exception handle_error() let me see more of the error:
except ValueError, ex:
self.handle_error()
type,value,traceback = sys.exc_info()
print type
#print "Collect Incoming Data: " . time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())
print "EX: ", ex
print "Data: ",repr(data)
Below is my new error, I've commented out personal data. It's apparent that the issue I really have now is in-fact the unterminated string
EX: Unterminated string starting at:
line 1 column 49 (char 48) Data:
'{"ap-hdop":0.55,"rtcmin":"31","ap-latdec":XX.XXX,"a' EX: No JSON object could be decoded Data:
'p-latdeg":34,"adc6":2006,"adc7":2007,"adc4":2004,"adc5":2005,"adc2":2002,"adc3":2003,"adc0":2000,"adc1":2001,"gpio-0":30,"gpio-1":50,"gpio-2":70,"speed":5.0,"adc8":2008,"rtcday":"01","longdeg":118,"longdec":XX.XXX,"altitude":31.0,"ap-speed":0.0,"ap-pdop":0.77,"lat-dir":"N","long-dir":"W","hdop":0.01,"ap-rf":0,"alt-units":"M","rtcdow":"2","callsign":"XXXXX","ap-callsign":"XXXXX","id":1,"ap-id":1,"rtcyear":"2016","rtcmon":"03","ap-vdop":0.66,"ap-lat-dir":"N","vdop":0.02,"rtchour":"22","latdec":XX.XXX,"latdeg":34,"ap-longdeg":118,"ap-longdec":XX.XXX,"rtcsec":"15","ap-altitude":86.0,"ap-long-dir":"W","pdop":0.01,"ap-alt-units":"M","faraday-port":0}'
OK my original question was answered which was "Why am I not catching the ValueError exception even though I am providing code to do just that?"
#tadhg McDonald-jensen was correct with his comment to remove my call to handle_error().
I still have some other issues but they are a different question. Thanks!
When I make a json POST request I am trying to incorporate a progress bar to monitor progress. However, I only see the progress bar when the task has completed (it shows up at 100%) so that's not very useful...
I also get the following warnings:
> response <- POST(url,config=progress(),body=data2)
|==============================================================================================================================================================================================================================| 100%
There were 50 or more warnings (use warnings() to see the first 50)
> warnings()
Warning messages:
1: In curl::curl_fetch_memory(url, handle = handle) :
progress callback must return boolean
2: In curl::curl_fetch_memory(url, handle = handle) :
progress callback must return boolean
3: In curl::curl_fetch_memory(url, handle = handle) :
progress callback must return boolean
etc.
I found this conversation about httr on github which seems to imply the problem has been solved, but I'm still getting the warnings. Any ideas how I can make this progress bar work? Thanks!
Per a comment below I tried
devtools:install_github("hadley/httr")
And got the following error:
Reloading installed httr
Error in get(method, envir = home) :
lazy-load database 'C:/Users/.../R/win-library/3.2/httr/R/httr.rdb' is corrupt
In addition: Warning message:
In get(method, envir = home) : internal error -3 in R_decompress1
> response <- POST(url,config=progress(),body=data2)
Error: could not find function "POST"
> library(httr)
Error in get(method, envir = home) :
lazy-load database 'C:/Users.../R/win-library/3.2/httr/R/httr.rdb' is corrupt
And when I tried calling library(httr),
In addition: Warning messages:
1: In .registerS3method(fin[i, 1], fin[i, 2], fin[i, 3], fin[i, 4], :
restarting interrupted promise evaluation
2: In get(method, envir = home) :
restarting interrupted promise evaluation
3: In get(method, envir = home) : internal error -3 in R_decompress1
Error: package or namespace load failed for ‘httr’.
I am using the R package rjson to download weather data from Wunderground.com. Often I leave the program to run and there are no problems, with the data being collected fine. However, often the program stops running and I get the following error message:
Error in fromJSON(paste(raw.data, collapse = "")) : unclosed string
In addition: Warning message:
In readLines(conn, n = -1L, ok = TRUE) :
incomplete final line found on 'http://api.wunderground.com/api/[my_API_code]/history_20121214pws:1/q/pws:IBIRMING7.json'
Does anyone know what this means, and how I can avoid it since it stops my program from collecting data as I would like?
Many thanks,
Ben
I can recreate your error message using the rjson package.
Here's an example that works.
rjson::fromJSON('{"x":"a string"}')
# $x
# [1] "a string"
If we omit a double quote from the value of x, then we get the error message.
rjson::fromJSON('{"x":"a string}')
# Error in rjson::fromJSON("{\"x\":\"a string}") : unclosed string
The RJSONIO package behaves slightly differently. Rather than throwing an error, it silently returns a NULL value.
RJSONIO::fromJSON('{"x":"a string}')
# $x
# NULL