Requests/httplib/urllib return 3 different results

685 views Asked by At

I'm making a GET request to OrientDB via their HTTP API, which seems to return 3 different results with the 3 aforementioned modules.

uri = 'http://localhost:2480/query/Test1/sql/Select from Person'

# Requests
import requests
r = requests.get(uri, auth = ('root', 'root'))
print r.status_code #200
r.json() # Returns the results from the query, all good

# httplib2
import httplib2
h = httplib2.Http()
h.add_credentials('root', 'root')
r = h.request(uri = uri, method = 'GET')
print r

#this returns status 200, but the response itself says 401 unauthorized.

#({'content-location': 'http://localhost:2480/query/Test1/sql/Select from Person',
#  'status': '200'},
# 'from 401 Unauthorized\r\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\r\nPragma: no-cache\r\nDate: Fri Jun 26 10:45:26 IDT 2015\r\nContent-Type: text/plain; charset=utf-8\r\nServer: OrientDB Server v.2.0.8 (build UNKNOWN@r; 2015-04-22 20:47:49+0000)\r\nConnection: Keep-Alive\r\nWWW-Authenticate: Basic realm="OrientDB db-Test1"\r\nSet-Cookie: OSESSIONID=-; Path=/; HttpOnly\r\nContent-Length: 17\r\n\r\n401 Unauthorized.')

# This however returns the correct result, meaning we are authorized!
h.request(uri = 'http://localhost:2480/document/Test1/12:0', 
        method = 'GET') 


#urllib3
import urllib3
http = urllib3.PoolManager()
headers = urllib3.util.make_headers(basic_auth = 'root:root')
r = http.request('GET', uri, headers = headers)
print r.data

# This returns some weird response, definitely not what I got with requests module. 
# This isn't the expected from my query either
# 'from 200 OK\r\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\r\nPragma: no-cache\r\nDate: Fri Jun 26 10:51:23 IDT 2015\r\nContent-Type: application/json; charset=utf-8\r\nServer: OrientDB Server v.2.0.8 (build UNKNOWN@r; 2015-04-22 20:47:49+0000)\r\nConnection: Keep-Alive\r\nSet-Cookie: OSESSIONID=OS1435305083836-80491934664057070; Path=/; HttpOnly\r\nContent-Length: 54\r\n\r\n{"result":[{"@type":"d","@rid":"#-2:0","@version":0}]}'

# This however returns actual results
http.request('GET', 'http://localhost:2480/document/Test1/12:0', headers = headers) 

I really don't have a clue what's going on here. Running the sql query request from the browser returns the expected results, same thing Requests did.

I also tried playing a bit with the headers, didn't help....

I can't tell if there's something wrong with

  • My code
  • The API
  • Me misunderstanding the purpose of each module, and hence misusing them

So, why is it that all three modules return three different results, and how do I make httplib & urllib return correct results?

Thanks!

Edit -

After reading this (thanks dano), I'm passed the 401 response with httplib2 by manually adding authentication headers to the request.

However httplib still returns the exact same response urllib does - A weird response with id = -2, which means nothing. Requests still returns the actual results.

Why is Requests the only one that manages to get actual results?!

1

There are 1 answers

3
dano On BEST ANSWER

I think what you're seeing with httplib2 is actually by design; when you provide credentials, httplib2 won't pass them on to the server in its first request. If the server returns a 401 status, it'll trying again with the credentials included. Since it looks like you're getting a 200 status back (despite the message saying it's a 401), it's probably not sending the creds. You can try to work around it by manually adding the credentials to the header of your request:

import base64
import httplib2

h = httplib2.Http()
auth = base64.encodestring( 'root' + ':' + 'root' )

r = h.request(uri, method='GET',
    headers = {'Authorization' : 'Basic ' + auth}
)

I'm not 100% sure, but my guess is that the urllib3 issue is due to the whitespace in your uri. See if it works with http.request_encode_url instead of http.request.