HTTPS get using Jython

2019-08-09 03:55发布

问题:

Please see my code below. Basically it's a script that queries an API service with a hostname as the parameter, which then returns some meta data associated with this server. Now, it works really well when executed from a Python 2.7 compiler that's been installed into a windows machine, also works using CURL from a bash CLI (meaning that the URL is definitely working), but this script will be running on an HP application that has an embedded JVM wrapper, meaning that it will use Jython and not CPython like my local machine - at least that's what I think the issue is. This is what causes the first problem - SSL handshake will fail because while CPython ignores certificates, Jython doesn't. Since the certificate of this internal API is self-signed, I get this:

jvm 1    | sslerror(-1, 'SSL handshake exception: Differences between the SSL socket behaviour of cpython vs. jython are explained on the wiki:  http://wiki.python.org/jython/NewSocketModule#SSL_Support')

When attempted using HTTP, I get error code 400:

400: ('Bad Request', 'Bad request syntax or unsupported method')

I think it's worth noting that it cannot be a network problem. I can get the data from the browser using HTTP just fine.

Ideally, I would be happy with unsecure HTTP since it's an internal service anyway. Also, trusting certs is going to be problematic since my script will run in 45-50 different machines, adding way too much overhead.

Also, using something other than urllib2 (Python requests module, for example) is going to be a problem, because anything non-ootb would have to be distributed to all the machines, again adding unacceptable overhead.

I have found this: trusting all certificates in Jython, but frankly I don't understand much.

I guess my question is: why HTTP fails?

EDIT: Imported some certs into JVM's keystore, now I seem to be passing the SSL layer but it still responds with code 400.

import urllib2
import base64
baseUrl = 'https://my-api-example.com/'
hostname = 'server1.example.com'
username = "vinnie"
password = 'pooh'
request = urllib2.Request(baseUrl + hostname)
base64string = base64.encodestring('%s:%s' % (username, password))
request.add_header("Authorization", "Basic %s" % base64string)
try:
    data = urllib2.urlopen(request)
    print data.read()
except urllib2.HTTPError, e:
    print e.code
except urllib2.URLError, e:
    print e.reason
except:
    print 'Undefined error'

回答1:

I managed to figure it out by myself by printing out the properties of the "request" instance. Doing so revealed that base64.encode apparently returns the string with a trailing newline symbol, which causes the server to respond with 400. I guess using encode would have bypassed the issue, although I can't understand why base64.encode gives the value back with a trailing newline in the first place.

Case closed...