2

I need to use the urllib for this, not urllib2, urllib3, or Requests.

The curl equivalent...

curl -H "Content-Type: application/json" -X POST -d '{"title":"My New Title","content":"blahblah","excerpt":"blah"}' http://localhost/wp-json/wp/v2/posts --user 'user:xxx' 

... and the following code work fine:

r = requests.post(url + '/wp-json/wp/v2/posts', auth=HTTPBasicAuth(username, password), data=json.dumps(params), headers={'content-type': 'application/json'}) if(not(r.ok)): raise Exception('failed with rc=' + r.status_code) return json.loads(r.text) 

But this fails:

params = { 'title': 'The Title', 'content': content, 'exerpt': 'blah' } postparam = json.dumps(params).encode('utf-8') password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() password_mgr.add_password(None, url, username, password) handler = urllib.request.HTTPBasicAuthHandler(password_mgr) opener = urllib.request.build_opener(handler) req = urllib.request.Request(url + '/wp-json/wp/v2/posts', method='POST', data=postparam) req.add_header('Content-Type', 'application/json') r = opener.open(req) if(r.getcode() != 200): raise Exception('failed with rc=' + r.getcode()) 

Traceback:

Traceback (most recent call last): File "test_wp_api.py", line 10, in <module> rs = create(endpoint, "test") File "C:\...\wordpress.py", line 28, in create r = opener.open(req) File "c:\usr\Python37-32\lib\urllib\request.py", line 531, in open response = meth(req, response) File "c:\usr\Python37-32\lib\urllib\request.py", line 641, in http_response 'http', request, response, code, msg, hdrs) File "c:\usr\Python37-32\lib\urllib\request.py", line 569, in error return self._call_chain(*args) File "c:\usr\Python37-32\lib\urllib\request.py", line 503, in _call_chain result = func(*args) File "c:\usr\Python37-32\lib\urllib\request.py", line 649, in http_error_default raise HTTPError(req.full_url, code, msg, hdrs, fp) urllib.error.HTTPError: HTTP Error 401: Unauthorized 

What's the cause, and how to fix it?

0

1 Answer 1

2

I will venture a guess. Please, try this out and if it does not address your issue, I can ditch the answer (but it won't easily fit into a comment as is).

Not sure about requests. but curl when provided with credentials does not wait for challenge (HTTP 401 and info on supported authentication methods) to try (respond with) authentication (attempt). Some servers do not send such challenge and just expect pre-authenticated session or a force (lucky guess a bit) authentication. I have to talk to some hosts like that too. If that is the case, you cannot change server setup and you are OK to just assume HTTP basic is supported, you can try forcing your credentials into each request. Reusing your opener,username, and password and you also need to import base64 for this snippet which does just that:

credentials = '{}:{}'.format(username, password).encode('ascii') credentials = base64.b64encode(credentials) credentials = b"Basic " + credentials opener.addheaders.append(("Authorization", credentials)) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.