douwaif22244 2013-01-16 11:56
浏览 38
已采纳

G-WAN,CGI脚本的输出头

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', "

"; // as first line

or in Go:

fmt.Print("Content-Type: text/plain

") // 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:
  • 写回答

1条回答 默认 最新

  • doubao6681 2013-01-16 16:11
    关注

    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
    ", os.Getenv("SERVER_PROTOCOL"))
       fmt.Print("Content-Type: text/html; charset=UTF-8
    ")
       fmt.Print("Connection: Keep-Alive
    ")
       fmt.Printf("Content-Length: %d
    ",len(p))
       fmt.Print("
    ")
       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
    ", os.Getenv("SERVER_PROTOCOL"))
    10|   fmt.Print("Content-Type: text/html; charset=UTF-8
    ")
    11|   fmt.Print("Connection: Keep-Alive
    ")
    
    
    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).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示