G-WAN,从CGI脚本输出头文件 [英] G-WAN, output headers from CGI script
问题描述
我试图通过CGI脚本设置一个HTTP头像 Content-Type
。
PHP
:
header('Content-Type:text / plain' );
//或
echo'Content-Type:text / plain',\r\\\
\r\\\
; //作为第一行
或在 Go
:
fmt.Print(Content-Type:text / plain \r\\\
\r\\\
)//作为第一行
两者都不会影响输出。
这怎么能做到?
编辑 p>我还使用 CGI
包在 Go
中尝试了以下内容:
软件包主要
导入fmt
导入os
导入net / http / cgi$如果e!= nil {
fmt.Println(e)
os .Exit(200)
}
fmt.Printf(%#v,r)
os.Exit(200)
}
但我得到错误:
cgi:未能将REQUEST_URI解析为URL:
问题1:
如果您的脚本返回一个有效的HTTP返回码(例如 200
),然后G-WAN构建相应的HTTP头,除非它们已经在那里(从HTTP / 1 .x 200 OK
here)。
因此,用脚本语言强制给定的 content-type
(除了那些支持像C,C ++,D和Objective-C这样的G-WAN API),你必须返回1
并定义你的回复的所有HTTP标题。 / p>
支持G-WAN API的编程语言可以使用 get_env(argv,REPLY_MIME_TYPE);
fractal.c
以及其他),并让G-WAN构建其余的标题。
$ b
问题2:
$ b 环境变量 REQUEST_URI
(虽然有用)不是支持的 CGI v1规范(RFC-3875)。我已要求在未来版本中添加 REQUEST_URI
。
G-WAN提供的脚本示例列出支持变量v3.12:
// ----------------- -------------------------------------------------- ---------
// CGI / 1.1环境变量:
// ----------------------- -------------------------------------------------- ---
//AUTH_TYPE,// //| 基本| 摘要|等等
//CONTENT_LENGTH,//| entity_length
//CONTENT_TYPE,//| content_type
//GATEWAY_INTERFACE,//CGI / 1.1
//PATH_INFO,//| (/路径)
//PATH_TRANSLATED,// PATH_INFO的磁盘文件名
//QUERY_STRING,//| ?hellox.c& name = toto
//REMOTE_ADDR,//客户端IP地址
//REMOTE_HOST,//客户端DNS名称(或IP地址)
/ /客户端标识(RFC 1413),opt
//REMOTE_USER,//客户端标识(如果认证)
//REQUEST_METHOD,//GET|REMOTE_IDENT HEAD| PUT等。
//SCRIPT_NAME,//| (/pathhello.c)
//SERVER_NAME,//gwan.com| IP地址
//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
pre>
// args [2] arg1 = 123
// args [3] arg2 = 456
for i:= 1;我< LEN(os.Args); i ++ {
fmt.Printf(args [%d]%s< br>,i,os.Args [i])
}
UPDATE
我们通过电子邮件收到了此源代码:
包主
$ b导入fmt
导入os
func main()
{
p:=< h1> Hello world!< / h1>< p>这是dog bla< / p>
fmt.Printf(%s 200 OK \r\\\
,os.Getenv(SERVER_PROTOCOL))
fmt.Print(Content-Type:text / html; charset = UTF (Content-Length:%d \r);
fmt.Print(Connection:Keep-Alive \r\\\
)
fmt.Printf \ n,len(p))
fmt.Print(\r\)
fmt.Print(p)
}
请注意,这段代码是不正确的:它甚至没有编译 - 而且G-WAN报告出现以下错误:
loading。
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
错误:hell.go
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~
#命令行参数
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:7:语法错误:意外的分号或换行符之前{
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:9:函数体外的非声明语句
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go :10:函数体外的非声明语句
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:11:函数体外的非声明语句
0.0.0.0_8080 /#0.0 .0.0 / csp / hell.go:12:函数体外的非声明语句
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:13:函数体外的非声明语句
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:14:函数体外的非声明语句
0.0.0.0_8080 /#0.0.0.0 / csp / hell.go:16:语法错误:意想不到的}
4 |导入os
5 |
6 | func main()
7!{
8 | p:=< h1> Hello world!< / h1>< p>这是dog bla< / p>
9 | fmt.Printf(%s 200 OK \r\\\
,os.Getenv(SERVER_PROTOCOL))
10 | fmt.Print(Content-Type:text / html; charset = UTF-8 \r \\\
)
11 | fmt.Print(Connection:Keep-Alive \r\\\
)
要运行G-WAN,您必须修复错误或删除此Servlet。
这很可能就是为什么你没有看到程序被更新:旧版本,如果有的话,不会被在G-WAN运行时更新的错误版本所取代。
当您开发(编辑脚本)时,您应该始终查看终端检查你的新编辑的代码是否编译。
我建议你看看(工作)
hello.go
例子看看main()
和(madatory)返回代码
的预期定义的要求是什么。 p>
如果没有使用返回码(就像在你的代码中那样),G-WAN会注入默认的HTTP头文件(
HTTP / 0.9 200 OK
在你的情况下),它将绕过你的HTTP标头(如果有的话),并因此,因特网浏览器将等待,直到它超时,因为它不知道你的答复的长度。
如示例和手册中所述,要告诉G-WAN不要创建HTTP头部,您必须在
1-99
范围内(0意味着关闭连接
且> 200-600保留给HTTP返回码
,告诉G-WAN生成对应的HTTP头)。I'm trying to set an HTTP header like
Content-Type
over a CGI script.In
PHP
:header('Content-Type: text/plain'); // or echo 'Content-Type: text/plain', "\r\n\r\n"; // as first line
or in
Go
:fmt.Print("Content-Type: text/plain\r\n\r\n") // as first line
Both have no effect on the output.
How can this be done?
EDIT
I also tried the following in
Go
, using theCGI
package: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) }
but I get the error:
cgi: failed to parse REQUEST_URI into a URL:
解决方案Question 1:
If your script returns a valid HTTP return code (like
200
) then G-WAN builds the corresponding HTTP Headers unless they are already there (starting with"HTTP/1.x 200 OK"
here).So, to force a given
content-type
with scripted languages (other than those which support the G-WAN API like C, C++, D, and Objective-C) you would have toreturn 1
and define ALL the HTTP headers of your reply.The programming languages that support the G-WAN API can use
get_env(argv, REPLY_MIME_TYPE);
(as shown infractal.c
and others) and let G-WAN build the rest of the headers.Question 2:
The environment variable
REQUEST_URI
(while useful) is not part of the supported CGI v1 specification (RFC-3875). I have requested thatREQUEST_URI
is added in a future release.The script examples provided with G-WAN list the supported variables by 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" // ----------------------------------------------------------------------------
Note that you can however access both the request and the parameters (if any) by using the following (and faster) Go code:
// 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]) }
UPDATE
We received this source code by email:
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) }
Please note that this code is incorrect: it does not even compile - and G-WAN reports the following errors:
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.
This is most probably why you haven't seen the program being "updated": the old version, if any, was not replaced by the faulty version updated while G-WAN was running.
When you develop (editing scripts) you should always have a look at the terminal to check if your newly edited code compiles.
I recommend you to look at the (working)
hello.go
example to see what the requirements are for the expected definition ofmain()
and the (madatory)return code
.When no return code is used (like in your code), G-WAN will inject default HTTP headers (
HTTP/0.9 200 OK
in your case) which will bypass your HTTP headers (if any) and as a result the Internet Browser will wait until it times-out because it does not know the length of your reply.As documented in the examples and in the manual, to tell G-WAN not to create HTTP headers you have to return a value in the
1-99
range (0 means close connection
and200-600 is reserved for HTTP return codes
that tell G-WAN to generate the correspondig HTTP headers).这篇关于G-WAN,从CGI脚本输出头文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!