@@ -21,6 +21,16 @@ import (
2121 "github.com/dunglas/frankenphp/internal/phpheaders"
2222)
2323
24+ // Protocol versions, in Apache mod_ssl format: https://httpd.apache.org/docs/current/mod/mod_ssl.html
25+ // Note that these are slightly different from SupportedProtocols in caddytls/config.go
26+ var tlsProtocolStrings = map [uint16 ]string {
27+ tls .VersionTLS10 : "TLSv1" ,
28+ tls .VersionTLS11 : "TLSv1.1" ,
29+ tls .VersionTLS12 : "TLSv1.2" ,
30+ tls .VersionTLS13 : "TLSv1.3" ,
31+ }
32+
33+ // Known $_SERVER keys
2434var knownServerKeys = []string {
2535 "CONTENT_LENGTH" ,
2636 "DOCUMENT_ROOT" ,
@@ -211,32 +221,92 @@ func go_register_variables(threadIndex C.uintptr_t, trackVarsArray *C.zval) {
211221 addPreparedEnvToServer (fc , trackVarsArray )
212222}
213223
224+ // splitCgiPath splits the request path into SCRIPT_NAME, SCRIPT_FILENAME, PATH_INFO, DOCUMENT_URI
225+ func splitCgiPath (fc * frankenPHPContext ) {
226+ path := fc .request .URL .Path
227+ splitPath := fc .splitPath
228+
229+ if splitPath == nil {
230+ splitPath = []string {".php" }
231+ }
232+
233+ if splitPos := splitPos (path , splitPath ); splitPos > - 1 {
234+ fc .docURI = path [:splitPos ]
235+ fc .pathInfo = path [splitPos :]
236+
237+ // Strip PATH_INFO from SCRIPT_NAME
238+ fc .scriptName = strings .TrimSuffix (path , fc .pathInfo )
239+
240+ // Ensure the SCRIPT_NAME has a leading slash for compliance with RFC3875
241+ // Info: https://tools.ietf.org/html/rfc3875#section-4.1.13
242+ if fc .scriptName != "" && ! strings .HasPrefix (fc .scriptName , "/" ) {
243+ fc .scriptName = "/" + fc .scriptName
244+ }
245+ }
246+
247+ // TODO: is it possible to delay this and avoid saving everything in the context?
248+ // SCRIPT_FILENAME is the absolute path of SCRIPT_NAME
249+ fc .scriptFilename = sanitizedPathJoin (fc .documentRoot , fc .scriptName )
250+ fc .worker = getWorkerByPath (fc .scriptFilename )
251+ }
252+
214253// splitPos returns the index where path should
215254// be split based on SplitPath.
255+ // example: if splitPath is [".php"]
256+ // "/path/to/script.php/some/path": ("/path/to/script.php", "/some/path")
216257//
217258// Adapted from https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/fastcgi/fastcgi.go
218259// Copyright 2015 Matthew Holt and The Caddy Authors
219- func splitPos (fc * frankenPHPContext , path string ) int {
220- if len (fc . splitPath ) == 0 {
260+ func splitPos (path string , splitPath [] string ) int {
261+ if len (splitPath ) == 0 {
221262 return 0
222263 }
223264
224265 lowerPath := strings .ToLower (path )
225- for _ , split := range fc . splitPath {
266+ for _ , split := range splitPath {
226267 if idx := strings .Index (lowerPath , strings .ToLower (split )); idx > - 1 {
227268 return idx + len (split )
228269 }
229270 }
230271 return - 1
231272}
232273
233- // Map of supported protocols to Apache ssl_mod format
234- // Note that these are slightly different from SupportedProtocols in caddytls/config.go
235- var tlsProtocolStrings = map [uint16 ]string {
236- tls .VersionTLS10 : "TLSv1" ,
237- tls .VersionTLS11 : "TLSv1.1" ,
238- tls .VersionTLS12 : "TLSv1.2" ,
239- tls .VersionTLS13 : "TLSv1.3" ,
274+ // go_update_request_info updates the sapi_request_info struct
275+ // See: https://github.com/php/php-src/blob/345e04b619c3bc11ea17ee02cdecad6ae8ce5891/main/SAPI.h#L72
276+ //
277+ //export go_update_request_info
278+ func go_update_request_info (threadIndex C.uintptr_t , info * C.sapi_request_info ) C.bool {
279+ thread := phpThreads [threadIndex ]
280+ fc := thread .getRequestContext ()
281+ request := fc .request
282+
283+ authUser , authPassword , ok := request .BasicAuth ()
284+ if ok {
285+ if authPassword != "" {
286+ info .auth_password = thread .pinCString (authPassword )
287+ }
288+ if authUser != "" {
289+ info .auth_user = thread .pinCString (authUser )
290+ }
291+ }
292+
293+ info .request_method = thread .pinCString (request .Method )
294+ info .query_string = thread .pinCString (request .URL .RawQuery )
295+ info .content_length = C .zend_long (request .ContentLength )
296+
297+ if contentType := request .Header .Get ("Content-Type" ); contentType != "" {
298+ info .content_type = thread .pinCString (contentType )
299+ }
300+
301+ if fc .pathInfo != "" {
302+ info .path_translated = thread .pinCString (sanitizedPathJoin (fc .documentRoot , fc .pathInfo )) // See: http://www.oreilly.com/openbook/cgi/ch02_04.html
303+ }
304+
305+ info .request_uri = thread .pinCString (request .URL .RequestURI ())
306+
307+ info .proto_num = C .int (request .ProtoMajor * 1000 + request .ProtoMinor )
308+
309+ return C .bool (fc .worker != nil )
240310}
241311
242312// SanitizedPathJoin performs filepath.Join(root, reqPath) that
0 commit comments