Skip to content

Instantly share code, notes, and snippets.

@jpschroeder
Last active January 8, 2023 02:05
Show Gist options
  • Save jpschroeder/ec1995db3c3366e589b9df4601d3e887 to your computer and use it in GitHub Desktop.
Save jpschroeder/ec1995db3c3366e589b9df4601d3e887 to your computer and use it in GitHub Desktop.
CGI Demo with Go
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo '<html><body>'
echo 'Hello From Bash <br/>Environment:'
echo '<pre>'
/usr/bin/env
echo '</pre>'
echo '</body></html>'
exit 0
#include <iostream>
using namespace std;
int main(int argc, char **argv, char **envp)
{
cout << "Content-type: text/html" << std::endl << std::endl;
cout << "<html><body>" << std::endl;
cout << "Hello From C++ <br/>Environment:" << std::endl;
cout << "<pre>" << std::endl;
for (char **env = envp; *env != 0; env++)
{
char *thisEnv = *env;
cout << thisEnv << std::endl;
}
cout << "</pre>" << std::endl;
cout << "</body></html>" << std::endl;
return 0;
}
package main
import (
"fmt"
"net/http"
"net/http/cgi"
)
func handler(w http.ResponseWriter, r *http.Request) {
header := w.Header()
header.Set("Content-Type", "text/html; charset=utf-8")
fmt.Fprintln(w, "<html><body>")
fmt.Fprintln(w, "Hello from Go Complex <br/> Environment:")
fmt.Fprintln(w, "<pre>")
fmt.Fprintln(w, "Method:", r.Method)
fmt.Fprintln(w, "URL:", r.URL.String())
query := r.URL.Query()
for k := range query {
fmt.Fprintln(w, "Query", k+":", query.Get(k))
}
r.ParseForm()
form := r.Form
for k := range form {
fmt.Fprintln(w, "Form", k+":", form.Get(k))
}
post := r.PostForm
for k := range post {
fmt.Fprintln(w, "PostForm", k+":", post.Get(k))
}
fmt.Fprintln(w, "RemoteAddr:", r.RemoteAddr)
if referer := r.Referer(); len(referer) > 0 {
fmt.Fprintln(w, "Referer:", referer)
}
if ua := r.UserAgent(); len(ua) > 0 {
fmt.Fprintln(w, "UserAgent:", ua)
}
for _, cookie := range r.Cookies() {
fmt.Fprintln(w, "Cookie", cookie.Name+":", cookie.Value, cookie.Path, cookie.Domain, cookie.RawExpires)
}
fmt.Fprintln(w, "</pre>")
fmt.Fprintln(w, "</body></html>")
}
func main() {
err := cgi.Serve(http.HandlerFunc(handler))
if err != nil {
fmt.Println(err)
}
}
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("Content-type: text/html")
fmt.Println("\n")
fmt.Println("<html><body>")
fmt.Println("Hello from Go Simple <br/> Environment:")
fmt.Println("<pre>")
for _, e := range os.Environ() {
fmt.Println(e)
}
fmt.Println("</pre>")
fmt.Println("</body></html>")
}
package main
import (
"fmt"
"log"
"net/http"
"net/http/cgi"
)
// Render links to child pages
func rootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `<html>
<body>
<a href="/bash?param1=value1">/bash</a> : bash cgi handler<br/>
<a href="/go-simple?param1=value1">/go-simple</a> : go simple cgi handler<br/>
<a href="/go-complex?param1=value1">/go-complex</a> : go complex cgi handler<br/>
<form action="/go-complex" method="post">
<input type="hidden" name="input2" value="value2" />
<input type="submit" value="/go-complex"/> : go complex cgi post<br/>
</form>
<a href="/cpp?param1=value1">/cpp</a> : c++ cgi handler<br/>
</body>
</html>`)
}
func cgiHandlerBash(w http.ResponseWriter, r *http.Request) {
handler := cgi.Handler{Path: "cgichild-bash.sh"}
handler.ServeHTTP(w, r)
}
func cgiHandlerGoSimple(w http.ResponseWriter, r *http.Request) {
handler := cgi.Handler{Path: "cgichild-go-simple"}
handler.ServeHTTP(w, r)
}
func cgiHandlerGoComplex(w http.ResponseWriter, r *http.Request) {
handler := cgi.Handler{Path: "cgichild-go-complex"}
handler.ServeHTTP(w, r)
}
func cgiHandlerCpp(w http.ResponseWriter, r *http.Request) {
handler := cgi.Handler{Path: "cgichild-cpp"}
handler.ServeHTTP(w, r)
}
func main() {
http.HandleFunc("/bash", cgiHandlerBash)
http.HandleFunc("/go-simple", cgiHandlerGoSimple)
http.HandleFunc("/go-complex", cgiHandlerGoComplex)
http.HandleFunc("/cpp", cgiHandlerCpp)
http.HandleFunc("/", rootHandler)
log.Println("Listening on http localhost:8080")
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
all: run
run: cgiserver
./cgiserver
cgiserver: cgiserver.go cgichild-go-simple cgichild-go-complex cgichild-cpp
go build cgiserver.go
cgichild-go-simple: cgichild-go-simple.go
go build cgichild-go-simple.go
cgichild-go-complex: cgichild-go-complex.go
go build cgichild-go-complex.go
cgichild-cpp: cgichild-cpp.cpp
g++ cgichild-cpp.cpp -o cgichild-cpp
clean:
rm cgichild-go-simple cgichild-go-complex cgichild-cpp cgiserver
.PHONY: all run clean
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment