@@ -481,14 +481,43 @@ func go_apache_request_headers(threadIndex C.uintptr_t) (*C.go_string, C.size_t)
481481}
482482
483483func addHeader (fc * frankenPHPContext , cString * C.char , length C.int ) {
484- parts := strings .SplitN (C .GoStringN (cString , length ), ": " , 2 )
485- if len (parts ) != 2 {
486- fc .logger .LogAttrs (context .Background (), slog .LevelDebug , "invalid header" , slog .String ("header" , parts [0 ]))
487-
484+ key , val := splitRawHeader (cString , int (length ))
485+ if key == "" {
486+ fc .logger .LogAttrs (context .Background (), slog .LevelDebug , "invalid header" , slog .String ("header" , C .GoStringN (cString , length )))
488487 return
489488 }
489+ fc .responseWriter .Header ().Add (key , val )
490+ }
491+
492+ // split the raw header coming from C with minimal allocations
493+ func splitRawHeader (rawHeader * C.char , length int ) (string , string ) {
494+ buf := unsafe .Slice ((* byte )(unsafe .Pointer (rawHeader )), length )
495+
496+ // Search for the colon in 'Header-Key: value'
497+ var i int
498+ for i = 0 ; i < length ; i ++ {
499+ if buf [i ] == ':' {
500+ break
501+ }
502+ }
503+
504+ if i == length {
505+ return "" , "" // No colon found, invalid header
506+ }
507+
508+ headerKey := C .GoStringN (rawHeader , C .int (i ))
509+
510+ // skip whitespaces after the colon
511+ j := i + 1
512+ for j < length && buf [j ] == ' ' {
513+ j ++
514+ }
515+
516+ // anything left is the header value
517+ valuePtr := (* C .char )(unsafe .Pointer (uintptr (unsafe .Pointer (rawHeader )) + uintptr (j )))
518+ headerValue := C .GoStringN (valuePtr , C .int (length - j ))
490519
491- fc . responseWriter . Header (). Add ( parts [ 0 ], parts [ 1 ])
520+ return headerKey , headerValue
492521}
493522
494523//export go_write_headers
0 commit comments