Skip to content

Commit a0181d8

Browse files
author
jczic
committed
Add CORS and origins support
1 parent b6a1860 commit a0181d8

File tree

7 files changed

+106
-52
lines changed

7 files changed

+106
-52
lines changed

MicroWebSrv2/httpRequest.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def _processRequest(self) :
8989
if not self._processRequestModules() :
9090
if not self.IsUpgrade :
9191
if not self._processRequestRoutes() :
92-
if self._method == 'GET' or self._method == 'HEAD' :
92+
if self._method in ('GET', 'HEAD') :
9393
filename = self._mws2.ResolvePhysicalPath(self._path)
9494
if filename :
9595
ct = self._mws2.GetMimeTypeFromFilename(filename)
@@ -101,6 +101,13 @@ def _processRequest(self) :
101101
self._response.ReturnForbidden()
102102
else :
103103
self._response.ReturnNotFound()
104+
elif self._method == 'OPTIONS' :
105+
if self._mws2.CORSAllowAll :
106+
self._response.SetHeader( 'Access-Control-Allow-Methods', '*' )
107+
self._response.SetHeader( 'Access-Control-Allow-Headers', '*' )
108+
self._response.SetHeader( 'Access-Control-Allow-Credentials', 'true' )
109+
self._response.SetHeader( 'Access-Control-Max-Age', '86400' )
110+
self._response.ReturnOk()
104111
else :
105112
self._response.ReturnMethodNotAllowed()
106113
else :

MicroWebSrv2/httpResponse.py

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,19 @@ class HttpResponse :
111111
# ------------------------------------------------------------------------
112112

113113
def __init__(self, microWebSrv2, request) :
114-
self._mws2 = microWebSrv2
115-
self._request = request
116-
self._xasCli = request.XAsyncTCPClient
117-
self._headers = { }
118-
self._allowCaching = False
119-
self._contentType = None
120-
self._contentCharset = None
121-
self._contentLength = 0
122-
self._stream = None
123-
self._sendingBuf = None
124-
self._hdrSent = False
125-
self._onSent = None
114+
self._mws2 = microWebSrv2
115+
self._request = request
116+
self._xasCli = request.XAsyncTCPClient
117+
self._headers = { }
118+
self._allowCaching = False
119+
self._acAllowOrigin = None
120+
self._contentType = None
121+
self._contentCharset = None
122+
self._contentLength = 0
123+
self._stream = None
124+
self._sendingBuf = None
125+
self._hdrSent = False
126+
self._onSent = None
126127

127128
# ------------------------------------------------------------------------
128129

@@ -207,6 +208,10 @@ def _makeBaseResponseHdr(self, code) :
207208
code,
208209
reason ),
209210
self._mws2.DEBUG )
211+
if self._mws2.AllowAllOrigins :
212+
self._acAllowOrigin = self._request.Origin
213+
if self._acAllowOrigin :
214+
self.SetHeader('Access-Control-Allow-Origin', self._acAllowOrigin)
210215
self.SetHeader('Server', 'MicroWebSrv2 by JC`zic')
211216
hdr = ''
212217
for n in self._headers :
@@ -476,6 +481,18 @@ def AllowCaching(self, value) :
476481

477482
# ------------------------------------------------------------------------
478483

484+
@property
485+
def AccessControlAllowOrigin(self) :
486+
return self._acAllowOrigin
487+
488+
@AccessControlAllowOrigin.setter
489+
def AccessControlAllowOrigin(self, value) :
490+
if value is not None and not isinstance(value, str) :
491+
raise ValueError('"AccessControlAllowOrigin" must be a string or None.')
492+
self._acAllowOrigin = value
493+
494+
# ------------------------------------------------------------------------
495+
479496
@property
480497
def ContentType(self) :
481498
return self._contentType

MicroWebSrv2/microWebSrv2.py

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,21 @@ class MicroWebSrv2 :
8181
# ------------------------------------------------------------------------
8282

8383
def __init__(self) :
84-
self._backlog = None
85-
self._slotsCount = None
86-
self._slotsSize = None
87-
self._keepAlloc = None
88-
self._maxContentLen = None
89-
self._bindAddr = ('0.0.0.0', 80)
90-
self._sslContext = None
91-
self._rootPath = 'www'
92-
self._timeoutSec = 2
93-
self._notFoundURL = None
94-
self._onLogging = None
95-
self._xasSrv = None
96-
self._xasPool = None
84+
self._backlog = None
85+
self._slotsCount = None
86+
self._slotsSize = None
87+
self._keepAlloc = None
88+
self._maxContentLen = None
89+
self._bindAddr = ('0.0.0.0', 80)
90+
self._sslContext = None
91+
self._rootPath = 'www'
92+
self._timeoutSec = 2
93+
self._notFoundURL = None
94+
self._allowAllOrigins = False
95+
self._corsAllowAll = False
96+
self._onLogging = None
97+
self._xasSrv = None
98+
self._xasPool = None
9799
self.SetNormalConfig()
98100

99101
# ------------------------------------------------------------------------
@@ -502,6 +504,30 @@ def NotFoundURL(self, value) :
502504

503505
# ------------------------------------------------------------------------
504506

507+
@property
508+
def AllowAllOrigins(self) :
509+
return self._allowAllOrigins
510+
511+
@AllowAllOrigins.setter
512+
def AllowAllOrigins(self, value) :
513+
if not isinstance(value, bool) :
514+
raise ValueError('"AllowAllOrigins" must be a boolean.')
515+
self._allowAllOrigins = value
516+
517+
# ------------------------------------------------------------------------
518+
519+
@property
520+
def CORSAllowAll(self) :
521+
return self._corsAllowAll
522+
523+
@CORSAllowAll.setter
524+
def CORSAllowAll(self, value) :
525+
if not isinstance(value, bool) :
526+
raise ValueError('"CORSAllowAll" must be a boolean.')
527+
self._corsAllowAll = value
528+
529+
# ------------------------------------------------------------------------
530+
505531
@property
506532
def OnLogging(self) :
507533
return self._onLogging

MicroWebSrv2/mods/WebSockets.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,10 @@ def OnRequest(self, microWebSrv2, request) :
3333
key = request.GetHeader('Sec-Websocket-Key')
3434
if key :
3535
try :
36-
origin = request.Origin
3736
key += WebSockets._HANDSHAKE_SIGN
3837
sec = sha1(key.encode()).digest()
3938
sec = b2a_base64(sec).decode().strip()
4039
protocols = request.GetHeader('Sec-WebSocket-Protocol')
41-
if origin :
42-
response.SetHeader('Access-Control-Allow-Origin', origin)
4340
response.SetHeader('Sec-WebSocket-Accept', sec)
4441
if protocols and self._onWebSocketProtocol :
4542
protocols = [x.strip() for x in protocols.split(',')]

MicroWebSrv2/webRoute.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,12 @@ def RegisterRoute(handler, method, routePath, name=None) :
7272

7373
def ResolveRoute(method, path) :
7474
try :
75+
path = path.lower()
7576
if len(path) > 1 and path.endswith('/') :
7677
path = path[:-1]
7778
for regRoute in _registeredRoutes :
7879
if regRoute.Method == method :
79-
reMatch = regRoute.Regex.match(path.lower())
80+
reMatch = regRoute.Regex.match(path)
8081
if reMatch :
8182
if not regRoute.ArgNames :
8283
return RouteResult(regRoute)

README.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,8 @@ except KeyboardInterrupt :
692692
| `RootPath` | str | :ballot_box_with_check: | :ballot_box_with_check: | *Path of the root folder that contains the web files.* |
693693
| `RequestsTimeoutSec` | int | :ballot_box_with_check: | :ballot_box_with_check: | *Timeout in seconds to waiting the next data reception of requests.* |
694694
| `NotFoundURL` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *URL used to redirects requests not found.* |
695+
| `AllowAllOrigins` | bool | :ballot_box_with_check: | :ballot_box_with_check: | *Indicates that all resource origins of requests are allowed.* |
696+
| `CORSAllowAll` | bool | :ballot_box_with_check: | :ballot_box_with_check: | *Allows all CORS values for the preflight requests (OPTIONS).* |
695697
| `OnLogging` | [callback](#mws2-onlogging) or None | :ballot_box_with_check: | :ballot_box_with_check: | *Callback function when the server logs information.* |
696698
697699
> **Definition of the above callback functions:**
@@ -1149,17 +1151,18 @@ except KeyboardInterrupt :
11491151
<a name="response-prop"></a>
11501152
- ### HttpResponse properties
11511153
1152-
| Name | Type | Get | Set | Description |
1153-
|------------------|:------------------------------------:|:-----------------------:|:-----------------------:|---------------------------------------------------------------------------------------------|
1154-
| `Request` | [HttpRequest](#request-class) | :ballot_box_with_check: | - | *Http request related to this response.* |
1155-
| `UserAddress` | tuple | :ballot_box_with_check: | - | *User remote address of the http connection such as a tuple of `(str_ip_addr, int_port)`.* |
1156-
| `IsSSL` | bool | :ballot_box_with_check: | - | *Indicates that the http connection is secured by SSL/TLS security layer with certificate.* |
1157-
| `AllowCaching` | bool | :ballot_box_with_check: | :ballot_box_with_check: | *Indicates to the user the possible caching of this response.* |
1158-
| `ContentType` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *Type of the content of this response.* |
1159-
| `ContentCharset` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *Encoding charset used for the content of this response.* |
1160-
| `ContentLength` | int | :ballot_box_with_check: | :ballot_box_with_check: | *Length of the content of this response.* |
1161-
| `HeadersSent` | bool | :ballot_box_with_check: | - | *Indicates that response http headers was already sent.* |
1162-
| `OnSent` | [callback](#response-onsent) or None | :ballot_box_with_check: | :ballot_box_with_check: | *Callback function when response is fully sent.* |
1154+
| Name | Type | Get | Set | Description |
1155+
|----------------------------|:------------------------------------:|:-----------------------:|:-----------------------:|---------------------------------------------------------------------------------------------|
1156+
| `Request` | [HttpRequest](#request-class) | :ballot_box_with_check: | - | *Http request related to this response.* |
1157+
| `UserAddress` | tuple | :ballot_box_with_check: | - | *User remote address of the http connection such as a tuple of `(str_ip_addr, int_port)`.* |
1158+
| `IsSSL` | bool | :ballot_box_with_check: | - | *Indicates that the http connection is secured by SSL/TLS security layer with certificate.* |
1159+
| `AllowCaching` | bool | :ballot_box_with_check: | :ballot_box_with_check: | *Indicates to the user the possible caching of this response.* |
1160+
| `AccessControlAllowOrigin` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *Indicates to the user the allowed resource origin.* |
1161+
| `ContentType` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *Type of the content of this response.* |
1162+
| `ContentCharset` | str or None | :ballot_box_with_check: | :ballot_box_with_check: | *Encoding charset used for the content of this response.* |
1163+
| `ContentLength` | int | :ballot_box_with_check: | :ballot_box_with_check: | *Length of the content of this response.* |
1164+
| `HeadersSent` | bool | :ballot_box_with_check: | - | *Indicates that response http headers was already sent.* |
1165+
| `OnSent` | [callback](#response-onsent) or None | :ballot_box_with_check: | :ballot_box_with_check: | *Callback function when response is fully sent.* |
11631166
11641167
> **Definition of the above callback functions:**
11651168

docs/index.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ except KeyboardInterrupt :
694694
| `RootPath` | str | Yes | Yes | *Path of the root folder that contains the web files.* |
695695
| `RequestsTimeoutSec` | int | Yes | Yes | *Timeout in seconds to waiting the next data reception of requests.* |
696696
| `NotFoundURL` | str or None | Yes | Yes | *URL used to redirects requests not found.* |
697+
| `AllowAllOrigins` | bool | Yes | Yes | *Indicates that all resource origins of requests are allowed.* |
698+
| `CORSAllowAll` | bool | Yes | Yes | *Allows all CORS values for the preflight requests (OPTIONS).* |
697699
| `OnLogging` | [callback](#mws2-onlogging) or None | Yes | Yes | *Callback function when the server logs information.* |
698700
699701
> **Definition of the above callback functions:**
@@ -1151,17 +1153,18 @@ except KeyboardInterrupt :
11511153
<a name="response-prop"></a>
11521154
- ### HttpResponse properties
11531155
1154-
| Name | Type | Get | Set | Description |
1155-
|------------------|:------------------------------------:|:-----------------------:|:-----------------------:|---------------------------------------------------------------------------------------------|
1156-
| `Request` | [HttpRequest](#request-class) | Yes | - | *Http request related to this response.* |
1157-
| `UserAddress` | tuple | Yes | - | *User remote address of the http connection such as a tuple of `(str_ip_addr, int_port)`.* |
1158-
| `IsSSL` | bool | Yes | - | *Indicates that the http connection is secured by SSL/TLS security layer with certificate.* |
1159-
| `AllowCaching` | bool | Yes | Yes | *Indicates to the user the possible caching of this response.* |
1160-
| `ContentType` | str or None | Yes | Yes | *Type of the content of this response.* |
1161-
| `ContentCharset` | str or None | Yes | Yes | *Encoding charset used for the content of this response.* |
1162-
| `ContentLength` | int | Yes | Yes | *Length of the content of this response.* |
1163-
| `HeadersSent` | bool | Yes | - | *Indicates that response http headers was already sent.* |
1164-
| `OnSent` | [callback](#response-onsent) or None | Yes | Yes | *Callback function when response is fully sent.* |
1156+
| Name | Type | Get | Set | Description |
1157+
|----------------------------|:------------------------------------:|:-----------------------:|:-----------------------:|---------------------------------------------------------------------------------------------|
1158+
| `Request` | [HttpRequest](#request-class) | Yes | - | *Http request related to this response.* |
1159+
| `UserAddress` | tuple | Yes | - | *User remote address of the http connection such as a tuple of `(str_ip_addr, int_port)`.* |
1160+
| `IsSSL` | bool | Yes | - | *Indicates that the http connection is secured by SSL/TLS security layer with certificate.* |
1161+
| `AllowCaching` | bool | Yes | Yes | *Indicates to the user the possible caching of this response.* |
1162+
| `AccessControlAllowOrigin` | str or None | Yes | Yes | *Indicates to the user the allowed resource origin.* |
1163+
| `ContentType` | str or None | Yes | Yes | *Type of the content of this response.* |
1164+
| `ContentCharset` | str or None | Yes | Yes | *Encoding charset used for the content of this response.* |
1165+
| `ContentLength` | int | Yes | Yes | *Length of the content of this response.* |
1166+
| `HeadersSent` | bool | Yes | - | *Indicates that response http headers was already sent.* |
1167+
| `OnSent` | [callback](#response-onsent) or None | Yes | Yes | *Callback function when response is fully sent.* |
11651168
11661169
> **Definition of the above callback functions:**
11671170

0 commit comments

Comments
 (0)