12
12
import imp
13
13
import pwd
14
14
import grp
15
+ import re
15
16
16
17
try :
17
18
import Queue as queue
@@ -243,6 +244,7 @@ def find_mimetypes():
243
244
send-buffer-size=%(send_buffer_size)s \\
244
245
receive-buffer-size=%(receive_buffer_size)s \\
245
246
header-buffer-size=%(header_buffer_size)s \\
247
+ proxy-buffer-size=%(proxy_buffer_size)s \\
246
248
server-metrics=%(daemon_server_metrics_flag)s
247
249
</IfDefine>
248
250
<IfDefine !WSGI_MULTIPROCESS>
@@ -265,7 +267,7 @@ def find_mimetypes():
265
267
shutdown-timeout=%(shutdown_timeout)s \\
266
268
send-buffer-size=%(send_buffer_size)s \\
267
269
receive-buffer-size=%(receive_buffer_size)s \\
268
- header -buffer-size=%(header_buffer_size )s \\
270
+ proxy -buffer-size=%(proxy_buffer_size )s \\
269
271
server-metrics=%(daemon_server_metrics_flag)s
270
272
</IfDefine>
271
273
</IfDefine>
@@ -618,6 +620,15 @@ def find_mimetypes():
618
620
PassEnv '%(name)s'
619
621
"""
620
622
623
+ APACHE_HANDLERS_CONFIG = """
624
+ WSGIHandlerScript wsgi-resource '%(server_root)s/resource.wsgi' \\
625
+ process-group='%(host)s:%(port)s' application-group=%%{GLOBAL}
626
+ """
627
+
628
+ APACHE_EXTENSION_CONFIG = """
629
+ AddHandler wsgi-resource %(extension)s
630
+ """
631
+
621
632
APACHE_INCLUDE_CONFIG = """
622
633
Include '%(filename)s'
623
634
"""
@@ -677,6 +688,13 @@ def generate_apache_config(options):
677
688
for name in options ['passenv_variables' ]:
678
689
print (APACHE_PASSENV_CONFIG % dict (name = name ), file = fp )
679
690
691
+ if options ['handler_scripts' ]:
692
+ print (APACHE_HANDLERS_CONFIG % options , file = fp )
693
+
694
+ for extension , script in options ['handler_scripts' ]:
695
+ print (APACHE_EXTENSION_CONFIG % dict (extension = extension ),
696
+ file = fp )
697
+
680
698
if options ['include_files' ]:
681
699
for filename in options ['include_files' ]:
682
700
filename = os .path .abspath (filename )
@@ -902,6 +920,48 @@ def handle_request(self, environ, start_response):
902
920
def __call__ (self , environ , start_response ):
903
921
return self .handle_request (environ , start_response )
904
922
923
+ class ResourceHandler (object ):
924
+
925
+ def __init__ (self , resources ):
926
+ self .resources = {}
927
+
928
+ for extension , script in resources :
929
+ extension_name = re .sub ('[^\w]{1}' , '_' , extension )
930
+ module_name = '__wsgi_resource%s__' % extension_name
931
+ module = imp .new_module (module_name )
932
+ module .__file__ = script
933
+
934
+ with open (script , 'r' ) as fp :
935
+ code = compile (fp .read (), script , 'exec' ,
936
+ dont_inherit = True )
937
+ exec (code , module .__dict__ )
938
+
939
+ sys .modules [module_name ] = module
940
+ self .resources [extension ] = module
941
+
942
+ def resource_extension (self , resource ):
943
+ return os .path .splitext (resource )[- 1 ]
944
+
945
+ def reload_required (self , resource ):
946
+ extension = self .resource_extension (resource )
947
+ function = getattr (self .resources [extension ], 'reload_required' , None )
948
+ if function is not None :
949
+ return function (environ )
950
+ return False
951
+
952
+ def handle_request (self , environ , start_response ):
953
+ resource = environ ['SCRIPT_NAME' ]
954
+ extension = self .resource_extension (resource )
955
+ module = self .resources [extension ]
956
+ function = getattr (module , 'handle_request' , None )
957
+ if function is not None :
958
+ return function (environ , start_response )
959
+ function = getattr (module , 'application' )
960
+ return function (environ , start_response )
961
+
962
+ def __call__ (self , environ , start_response ):
963
+ return self .handle_request (environ , start_response )
964
+
905
965
WSGI_HANDLER_SCRIPT = """
906
966
import mod_wsgi.server
907
967
@@ -926,6 +986,17 @@ def __call__(self, environ, start_response):
926
986
mod_wsgi.server.start_reloader()
927
987
"""
928
988
989
+ WSGI_RESOURCE_SCRIPT = """
990
+ import mod_wsgi.server
991
+
992
+ resources = %(resources)s
993
+
994
+ handler = mod_wsgi.server.ResourceHandler(resources)
995
+
996
+ reload_required = handler.reload_required
997
+ handle_request = handler.handle_request
998
+ """
999
+
929
1000
WSGI_DEFAULT_SCRIPT = """
930
1001
CONTENT = b'''
931
1002
<html>
@@ -975,6 +1046,11 @@ def generate_wsgi_handler_script(options):
975
1046
with open (path , 'w' ) as fp :
976
1047
print (WSGI_HANDLER_SCRIPT % options , file = fp )
977
1048
1049
+ path = os .path .join (options ['server_root' ], 'resource.wsgi' )
1050
+ with open (path , 'w' ) as fp :
1051
+ print (WSGI_RESOURCE_SCRIPT % dict (resources = repr (
1052
+ options ['handler_scripts' ])), file = fp )
1053
+
978
1054
path = os .path .join (options ['server_root' ], 'default.wsgi' )
979
1055
with open (path , 'w' ) as fp :
980
1056
print (WSGI_DEFAULT_SCRIPT % options , file = fp )
@@ -1275,6 +1351,12 @@ def check_percentage(option, opt_str, value, parser):
1275
1351
metavar = 'NUMBER' , help = 'Size of buffer used for reading '
1276
1352
'response headers from daemon processes. Defaults to 0, '
1277
1353
'indicating internal default of 32768 bytes is used.' ),
1354
+ optparse .make_option ('--proxy-buffer-size' , type = 'int' , default = 0 ,
1355
+ metavar = 'NUMBER' , help = 'Maximum amount of response content '
1356
+ 'that will be allowed to be buffered in the Apache child '
1357
+ 'worker process when proxying the response from a daemon '
1358
+ 'process. Defaults to 0, indicating internal default of '
1359
+ '65536 bytes is used.' ),
1278
1360
1279
1361
optparse .make_option ('--reload-on-changes' , action = 'store_true' ,
1280
1362
default = False , help = 'Flag indicating whether worker processes '
@@ -1362,7 +1444,7 @@ def check_percentage(option, opt_str, value, parser):
1362
1444
default = None , help = 'Specify a Python script file for '
1363
1445
'performing group based authorization in conjunction with '
1364
1446
'a user authentication script.' ),
1365
- optparse .make_option ('--auth-group' , metavar = 'SCRIPT-PATH ' ,
1447
+ optparse .make_option ('--auth-group' , metavar = 'NAME ' ,
1366
1448
default = 'wsgi' , help = 'Specify the group which users should '
1367
1449
'be a member of when using a group based authorization script. '
1368
1450
'Defaults to \' wsgi\' as a place holder but should be '
@@ -1450,6 +1532,12 @@ def check_percentage(option, opt_str, value, parser):
1450
1532
metavar = 'FILE-PATH' , help = 'Override the path to the mime types '
1451
1533
'file used by the web server.' ),
1452
1534
1535
+ optparse .make_option ('--add-handler' , action = 'append' , nargs = 2 ,
1536
+ dest = 'handler_scripts' , metavar = 'EXTENSION SCRIPT-PATH' ,
1537
+ help = 'Specify a WSGI application to be used as a special '
1538
+ 'handler for any resources matched from the document root '
1539
+ 'directory with a specific extension type.' ),
1540
+
1453
1541
optparse .make_option ('--with-newrelic' , action = 'store_true' ,
1454
1542
default = False , help = 'Flag indicating whether all New Relic '
1455
1543
'performance monitoring features should be enabled.' ),
@@ -1644,6 +1732,14 @@ def _cmd_setup_server(command, args, options):
1644
1732
else :
1645
1733
options ['daemon_server_metrics_flag' ] = 'Off'
1646
1734
1735
+ if options ['handler_scripts' ]:
1736
+ handler_scripts = []
1737
+ for extension , script in options ['handler_scripts' ]:
1738
+ if not os .path .isabs (script ):
1739
+ script = os .path .abspath (script )
1740
+ handler_scripts .append ((extension , script ))
1741
+ options ['handler_scripts' ] = handler_scripts
1742
+
1647
1743
if options ['with_newrelic' ]:
1648
1744
options ['with_newrelic_agent' ] = True
1649
1745
options ['with_newrelic_platform' ] = True
@@ -1902,7 +1998,7 @@ def cmd_install_module(params):
1902
1998
parser .error ('Incorrect number of arguments.' )
1903
1999
1904
2000
target = os .path .abspath (os .path .join (options .modules_directory ,
1905
- MOD_WSGI_SO ))
2001
+ os . path . basename ( MOD_WSGI_SO ) ))
1906
2002
1907
2003
shutil .copyfile (where (), target )
1908
2004
0 commit comments