113
113
(at your option) any later version.
114
114
"""
115
115
116
+ import copy
117
+ import os
118
+ import signal
119
+ import ssl
120
+ import sys
121
+ import urllib .parse
122
+
123
+ from http .server import BaseHTTPRequestHandler , HTTPServer
124
+ from qgis .core import QgsApplication
125
+ from qgis .server import (QgsBufferServerRequest , QgsBufferServerResponse ,
126
+ QgsServer , QgsServerRequest )
127
+
116
128
__author__ = 'Alessandro Pasotti'
117
129
__date__ = '05/15/2016'
118
130
__copyright__ = 'Copyright 2016, The QGIS Project'
119
131
# This will get replaced with a git SHA1 when you do a git archive
120
132
__revision__ = '$Format:%H$'
121
133
122
134
123
- import os
124
-
125
- # Needed on Qt 5 so that the serialization of XML is consistent among all executions
135
+ # Needed on Qt 5 so that the serialization of XML is consistent among all
136
+ # executions
126
137
os .environ ['QT_HASH_SEED' ] = '1'
127
138
128
139
import sys
142
153
QGIS_SERVER_HOST = os .environ .get ('QGIS_SERVER_HOST' , '127.0.0.1' )
143
154
144
155
# HTTP Basic
145
- QGIS_SERVER_HTTP_BASIC_AUTH = os .environ .get ('QGIS_SERVER_HTTP_BASIC_AUTH' , False )
156
+ QGIS_SERVER_HTTP_BASIC_AUTH = os .environ .get (
157
+ 'QGIS_SERVER_HTTP_BASIC_AUTH' , False )
146
158
QGIS_SERVER_USERNAME = os .environ .get ('QGIS_SERVER_USERNAME' , 'username' )
147
159
QGIS_SERVER_PASSWORD = os .environ .get ('QGIS_SERVER_PASSWORD' , 'password' )
148
160
153
165
QGIS_SERVER_PKI_USERNAME = os .environ .get ('QGIS_SERVER_PKI_USERNAME' )
154
166
155
167
# OAuth2 authentication
156
- QGIS_SERVER_OAUTH2_CERTIFICATE = os .environ .get ('QGIS_SERVER_OAUTH2_CERTIFICATE' )
168
+ QGIS_SERVER_OAUTH2_CERTIFICATE = os .environ .get (
169
+ 'QGIS_SERVER_OAUTH2_CERTIFICATE' )
157
170
QGIS_SERVER_OAUTH2_KEY = os .environ .get ('QGIS_SERVER_OAUTH2_KEY' )
158
171
QGIS_SERVER_OAUTH2_AUTHORITY = os .environ .get ('QGIS_SERVER_OAUTH2_AUTHORITY' )
159
- QGIS_SERVER_OAUTH2_USERNAME = os .environ .get ('QGIS_SERVER_OAUTH2_USERNAME' , 'username' )
160
- QGIS_SERVER_OAUTH2_PASSWORD = os .environ .get ('QGIS_SERVER_OAUTH2_PASSWORD' , 'password' )
161
- QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN = os .environ .get ('QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN' , 3600 )
172
+ QGIS_SERVER_OAUTH2_USERNAME = os .environ .get (
173
+ 'QGIS_SERVER_OAUTH2_USERNAME' , 'username' )
174
+ QGIS_SERVER_OAUTH2_PASSWORD = os .environ .get (
175
+ 'QGIS_SERVER_OAUTH2_PASSWORD' , 'password' )
176
+ QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN = os .environ .get (
177
+ 'QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN' , 3600 )
162
178
163
179
# Check if PKI is enabled
164
180
QGIS_SERVER_PKI_AUTH = (
@@ -218,7 +234,8 @@ def responseComplete(self):
218
234
# No auth ...
219
235
handler .clear ()
220
236
handler .setResponseHeader ('Status' , '401 Authorization required' )
221
- handler .setResponseHeader ('WWW-Authenticate' , 'Basic realm="QGIS Server"' )
237
+ handler .setResponseHeader (
238
+ 'WWW-Authenticate' , 'Basic realm="QGIS Server"' )
222
239
handler .appendBody (b'<h1>Authorization required</h1>' )
223
240
224
241
filter = HTTPBasicFilter (qgs_server .serverInterface ())
@@ -307,7 +324,8 @@ def save_bearer_token(self, token, request, *args, **kwargs):
307
324
# access_token and the refresh_token and set expiration for the
308
325
# access_token to now + expires_in seconds.
309
326
_tokens [token ['access_token' ]] = copy .copy (token )
310
- _tokens [token ['access_token' ]]['expiration' ] = datetime .now ().timestamp () + int (token ['expires_in' ])
327
+ _tokens [token ['access_token' ]]['expiration' ] = datetime .now (
328
+ ).timestamp () + int (token ['expires_in' ])
311
329
312
330
def validate_bearer_token (self , token , scopes , request ):
313
331
"""Check the token"""
@@ -325,7 +343,8 @@ def get_original_scopes(self, refresh_token, request, *args, **kwargs):
325
343
return []
326
344
327
345
validator = SimpleValidator ()
328
- oauth_server = LegacyApplicationServer (validator , token_expires_in = QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN )
346
+ oauth_server = LegacyApplicationServer (
347
+ validator , token_expires_in = QGIS_SERVER_OAUTH2_TOKEN_EXPIRES_IN )
329
348
330
349
class OAuth2Filter (QgsServerFilter ):
331
350
"""This filter provides testing endpoint for OAuth2 Resource Owner Grant Flow
@@ -349,7 +368,8 @@ def _token(ttl):
349
368
old_expires_in = oauth_server .default_token_type .expires_in
350
369
# Hacky way to dynamically set token expiration time
351
370
oauth_server .default_token_type .expires_in = ttl
352
- headers , payload , code = oauth_server .create_token_response ('/token' , 'post' , body , {})
371
+ headers , payload , code = oauth_server .create_token_response (
372
+ '/token' , 'post' , body , {})
353
373
oauth_server .default_token_type .expires_in = old_expires_in
354
374
for k , v in headers .items ():
355
375
handler .setResponseHeader (k , v )
@@ -371,9 +391,11 @@ def _token(ttl):
371
391
# Check for valid token
372
392
auth = handler .requestHeader ('HTTP_AUTHORIZATION' )
373
393
if auth :
374
- result , response = oauth_server .verify_request (handler .url (), 'post' , '' , {'Authorization' : auth })
394
+ result , response = oauth_server .verify_request (
395
+ urllib .parse .quote_plus (handler .url (), safe = '/:?=&' ), 'post' , '' , {'Authorization' : auth })
375
396
if result :
376
- # This is a test endpoint for OAuth2, it requires a valid token
397
+ # This is a test endpoint for OAuth2, it requires a valid
398
+ # token
377
399
if handler .url ().find ('/result' ) != - 1 :
378
400
handler .clear ()
379
401
handler .appendBody (b'Valid Token: enjoy OAuth2' )
@@ -387,7 +409,8 @@ def _token(ttl):
387
409
handler .clear ()
388
410
handler .setStatusCode (401 )
389
411
handler .setResponseHeader ('Status' , '401 Unauthorized' )
390
- handler .setResponseHeader ('WWW-Authenticate' , 'Bearer realm="QGIS Server"' )
412
+ handler .setResponseHeader (
413
+ 'WWW-Authenticate' , 'Bearer realm="QGIS Server"' )
391
414
handler .appendBody (b'Invalid Token: Authorization required.' )
392
415
393
416
filter = OAuth2Filter (qgs_server .serverInterface ())
@@ -401,10 +424,17 @@ def do_GET(self, post_body=None):
401
424
# CGI vars:
402
425
headers = {}
403
426
for k , v in self .headers .items ():
427
+ < << << << a7fb4238893336c8d5b2b4802f63588175e70c83
404
428
headers ['HTTP_%s' % k .replace (' ' , '-' ).replace ('-' , '_' ).replace (' ' , '-' ).upper ()] = v
405
429
if not self .path .startswith ('http' ):
406
430
self .path = "%s://%s:%s%s" % ('https' if https else 'http' , QGIS_SERVER_HOST , self .server .server_port , self .path )
407
431
request = QgsBufferServerRequest (self .path , (QgsServerRequest .PostMethod if post_body is not None else QgsServerRequest .GetMethod ), headers , post_body )
432
+ == == == =
433
+ headers ['HTTP_%s' % k .replace (
434
+ ' ' , '-' ).replace ('-' , '_' ).replace (' ' , '-' ).upper ()] = v
435
+ request = QgsBufferServerRequest (
436
+ self .path , (QgsServerRequest .PostMethod if post_body is not None else QgsServerRequest .GetMethod ), headers , post_body )
437
+ >> >> >> > Pass urlencoded URL to the oauth handler
408
438
response = QgsBufferServerResponse ()
409
439
qgs_server .handleRequest (request , response )
410
440
@@ -455,7 +485,7 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
455
485
ca_certs = QGIS_SERVER_OAUTH2_AUTHORITY ,
456
486
keyfile = QGIS_SERVER_OAUTH2_KEY ,
457
487
server_side = True ,
458
- #cert_reqs=ssl.CERT_REQUIRED, # No certs for OAuth2
488
+ # cert_reqs=ssl.CERT_REQUIRED, # No certs for OAuth2
459
489
ssl_version = ssl .PROTOCOL_TLSv1 )
460
490
else :
461
491
server .socket = ssl .wrap_socket (
0 commit comments