Я пытаюсь установить HTTP-заголовок, например Content-Type
по сценарию CGI.
В PHP
:
header('Content-Type: text/plain'); // or echo 'Content-Type: text/plain', "\r\n\r\n"; // as first line
или в Go
:
fmt.Print("Content-Type: text/plain\r\n\r\n") // as first line
Оба не влияют на выход.
Как это может быть сделано?
РЕДАКТИРОВАТЬ
Я также попробовал следующее в Go
, используя пакет CGI
:
package main import "fmt" import "os" import "net/http/cgi" func main() { r,e := cgi.Request() if e != nil { fmt.Println(e) os.Exit(200) } fmt.Printf("%#v", r) os.Exit(200) }
но я получаю ошибку:
cgi: failed to parse REQUEST_URI into a URL:
Вопрос 1:
Если ваш скрипт возвращает действительный код возврата HTTP (например, 200
), то G-WAN строит соответствующие заголовки HTTP, если они уже не существуют (начиная с "HTTP/1.x 200 OK"
здесь).
Таким образом, чтобы заставить заданный content-type
со сценарием (кроме тех, которые поддерживают API-интерфейс G-WAN, например C, C ++, D и Objective-C), вам нужно будет return 1
и определить ВСЕ HTTP-заголовки вашего ответа ,
Языки программирования, поддерживающие API G-WAN, могут использовать get_env(argv, REPLY_MIME_TYPE);
(как показано в fractal.c
и др.), и пусть G-WAN построит остальные заголовки.
Вопрос 2:
Переменная среды REQUEST_URI
(хотя и полезна) не является частью поддерживаемой спецификации CGI v1 (RFC-3875). Я попросил, чтобы REQUEST_URI
был добавлен в будущую версию.
Примеры скриптов, предоставленные G-WAN, перечисляют поддерживаемые переменные на v3.12:
// ---------------------------------------------------------------------------- // CGI/1.1 environment variables: // ---------------------------------------------------------------------------- // "AUTH_TYPE", // "" | "Basic" | "Digest" | etc. // "CONTENT_LENGTH", // "" | entity_length // "CONTENT_TYPE", // "" | content_type // "GATEWAY_INTERFACE", // "CGI/1.1" // "PATH_INFO", // "" | ( "/" path ) // "PATH_TRANSLATED", // disk filename for PATH_INFO // "QUERY_STRING", // "" | ?"hellox.c&name=toto" // "REMOTE_ADDR", // client IP address // "REMOTE_HOST", // client DNS name (or IP addr) // "REMOTE_IDENT", // client identity (RFC 1413), opt // "REMOTE_USER", // client identity (if auth) // "REQUEST_METHOD", // "GET" | "HEAD" | "PUT", etc. // "SCRIPT_NAME", // "" | ("/" path "hello.c") // "SERVER_NAME", // "gwan.com" | IP address // "SERVER_PORT", // "80" // "SERVER_PROTOCOL", // "HTTP/1.1" | "HTTP/1.0" | "HTTP/0.9" // "SERVER_SOFTWARE", // "G-WAN" // ----------------------------------------------------------------------------
Обратите внимание, что вы можете получить доступ как к запросу, так и к параметрам (если они есть), используя следующий (и более быстрый) код Go:
// args[1] /opt/gwan/10.10.20.80_80/#192.168.200.80/csp/hello.go // args[2] arg1=123 // args[3] arg2=456 for i := 1; i < len(os.Args); i++ { fmt.Printf("args[%d] %s<br>", i, os.Args[i]) }
Мы получили этот исходный код по электронной почте:
package main import "fmt" import "os" func main() { p := "<h1>Hello world!</h1><p>This is dog bla</p>" fmt.Printf("%s 200 OK\r\n", os.Getenv("SERVER_PROTOCOL")) fmt.Print("Content-Type: text/html; charset=UTF-8\r\n") fmt.Print("Connection: Keep-Alive\r\n") fmt.Printf("Content-Length: %d\r\n",len(p)) fmt.Print("\r\n") fmt.Print(p) }
Обратите внимание, что этот код неверен: он даже не компилируется – и G-WAN сообщает о следующих ошибках:
loading. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error: hell.go ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # command-line-arguments 0.0.0.0_8080/#0.0.0.0/csp/hell.go:7: syntax error: unexpected semicolon or newline before { 0.0.0.0_8080/#0.0.0.0/csp/hell.go:9: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:10: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:11: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:12: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:13: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:14: non-declaration statement outside function body 0.0.0.0_8080/#0.0.0.0/csp/hell.go:16: syntax error: unexpected } 4|import "os" 5| 6|func main() 7!{ 8| p := "<h1>Hello world!</h1><p>This is dog bla</p>" 9| fmt.Printf("%s 200 OK\r\n", os.Getenv("SERVER_PROTOCOL")) 10| fmt.Print("Content-Type: text/html; charset=UTF-8\r\n") 11| fmt.Print("Connection: Keep-Alive\r\n") To run G-WAN, you must fix the error(s) or remove this Servlet.
Вероятно, именно поэтому вы не заметили, что программа «обновлена»: старая версия, если она есть, не была заменена неисправной версией, обновленной во время работы G-WAN.
Когда вы разрабатываете (редактируете скрипты), вы всегда должны смотреть на терминал, чтобы проверить, компилируется ваш недавно отредактированный код.
Я рекомендую вам посмотреть пример (рабочий) hello.go
чтобы узнать, какие требования для ожидаемого определения main()
и (сумасшедшего) return code
.
Если код возврата не используется (например, в вашем коде), G-WAN будет вводить заголовки HTTP/0.9 200 OK
умолчанию ( HTTP/0.9 200 OK
в вашем случае), которые будут обходить ваши HTTP-заголовки (если есть), и в результате Internet-браузер будет ждать пока он не истечет, потому что он не знает длины вашего ответа.
Как указано в примерах и в руководстве, чтобы сообщить G-WAN не создавать заголовки HTTP, вам нужно вернуть значение в диапазоне 1-99
( 0 means close connection
а 200-600 is reserved for HTTP return codes
которые сообщают G -WAN для генерации соответствующих HTTP-заголовков).