G-WAN,从CGI脚本输出头文件 [英] G-WAN, output headers from CGI script

查看:106
本文介绍了G-WAN,从CGI脚本输出头文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过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 
// 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])
}
pre>




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 the CGI 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 to return 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 in fractal.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 that REQUEST_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 of main() 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 and 200-600 is reserved for HTTP return codes that tell G-WAN to generate the correspondig HTTP headers).

这篇关于G-WAN,从CGI脚本输出头文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆