| Index: experimental/webtry/webtry.go
|
| diff --git a/experimental/webtry/webtry.go b/experimental/webtry/webtry.go
|
| index 73e9fda993d6697dd404572827499e0828ccb56d..8e02a751a32f6786f00cb669a837e02d01f9602a 100644
|
| --- a/experimental/webtry/webtry.go
|
| +++ b/experimental/webtry/webtry.go
|
| @@ -135,12 +135,14 @@ func init() {
|
| indexTemplate, err = htemplate.ParseFiles(
|
| filepath.Join(cwd, "templates/index.html"),
|
| filepath.Join(cwd, "templates/titlebar.html"),
|
| + filepath.Join(cwd, "templates/content.html"),
|
| )
|
| if err != nil {
|
| panic(err)
|
| }
|
| iframeTemplate, err = htemplate.ParseFiles(
|
| filepath.Join(cwd, "templates/iframe.html"),
|
| + filepath.Join(cwd, "templates/content.html"),
|
| )
|
| if err != nil {
|
| panic(err)
|
| @@ -155,6 +157,7 @@ func init() {
|
| workspaceTemplate, err = htemplate.ParseFiles(
|
| filepath.Join(cwd, "templates/workspace.html"),
|
| filepath.Join(cwd, "templates/titlebar.html"),
|
| + filepath.Join(cwd, "templates/content.html"),
|
| )
|
| if err != nil {
|
| panic(err)
|
| @@ -220,8 +223,8 @@ func init() {
|
|
|
| // userCode is used in template expansion.
|
| type userCode struct {
|
| - UserCode string
|
| - Hash string
|
| + Code string
|
| + Hash string
|
| }
|
|
|
| // expandToFile expands the template and writes the result to the file.
|
| @@ -231,7 +234,7 @@ func expandToFile(filename string, code string, t *template.Template) error {
|
| return err
|
| }
|
| defer f.Close()
|
| - return t.Execute(f, userCode{UserCode: code})
|
| + return t.Execute(f, userCode{Code: code})
|
| }
|
|
|
| // expandCode expands the template into a file and calculate the MD5 hash.
|
| @@ -249,6 +252,7 @@ func expandCode(code string) (string, error) {
|
| // response is serialized to JSON as a response to POSTs.
|
| type response struct {
|
| Message string `json:"message"`
|
| + StdOut string `json:"stdout"`
|
| Img string `json:"img"`
|
| Hash string `json:"hash"`
|
| }
|
| @@ -298,8 +302,15 @@ func doCmd(commandLine string, moveToDebug bool) (string, error) {
|
|
|
| // reportError formats an HTTP error response and also logs the detailed error message.
|
| func reportError(w http.ResponseWriter, r *http.Request, err error, message string) {
|
| + log.Printf("Error: %s\n%s", message, err.Error())
|
| + http.Error(w, message, 500)
|
| +}
|
| +
|
| +// reportTryError formats an HTTP error response in JSON and also logs the detailed error message.
|
| +func reportTryError(w http.ResponseWriter, r *http.Request, err error, message, hash string) {
|
| m := response{
|
| Message: message,
|
| + Hash: hash,
|
| }
|
| log.Printf("Error: %s\n%s", message, err.Error())
|
| resp, err := json.Marshal(m)
|
| @@ -499,7 +510,7 @@ func iframeHandler(w http.ResponseWriter, r *http.Request) {
|
| return
|
| }
|
| // Expand the template.
|
| - if err := iframeTemplate.Execute(w, userCode{UserCode: code, Hash: hash}); err != nil {
|
| + if err := iframeTemplate.Execute(w, userCode{Code: code, Hash: hash}); err != nil {
|
| log.Printf("ERROR: Failed to expand template: %q\n", err)
|
| }
|
| }
|
| @@ -540,6 +551,12 @@ func tryInfoHandler(w http.ResponseWriter, r *http.Request) {
|
| w.Write(resp)
|
| }
|
|
|
| +func cleanCompileOutput(s, hash string) string {
|
| + old := "../../../cache/" + hash + ".cpp:"
|
| + log.Printf("INFO: replacing %q\n", old)
|
| + return strings.Replace(s, old, "usercode.cpp:", -1)
|
| +}
|
| +
|
| // mainHandler handles the GET and POST of the main page.
|
| func mainHandler(w http.ResponseWriter, r *http.Request) {
|
| log.Printf("Main Handler: %q\n", r.URL.Path)
|
| @@ -560,7 +577,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
|
| }
|
| }
|
| // Expand the template.
|
| - if err := indexTemplate.Execute(w, userCode{UserCode: code, Hash: hash}); err != nil {
|
| + if err := indexTemplate.Execute(w, userCode{Code: code, Hash: hash}); err != nil {
|
| log.Printf("ERROR: Failed to expand template: %q\n", err)
|
| }
|
| } else if r.Method == "POST" {
|
| @@ -568,38 +585,40 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
|
| buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE))
|
| n, err := buf.ReadFrom(r.Body)
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to read a request body.")
|
| + reportTryError(w, r, err, "Failed to read a request body.", "")
|
| return
|
| }
|
| if n == MAX_TRY_SIZE {
|
| err := fmt.Errorf("Code length equal to, or exceeded, %d", MAX_TRY_SIZE)
|
| - reportError(w, r, err, "Code too large.")
|
| + reportTryError(w, r, err, "Code too large.", "")
|
| return
|
| }
|
| request := TryRequest{}
|
| if err := json.Unmarshal(buf.Bytes(), &request); err != nil {
|
| - reportError(w, r, err, "Coulnd't decode JSON.")
|
| + reportTryError(w, r, err, "Coulnd't decode JSON.", "")
|
| return
|
| }
|
| if hasPreProcessor(request.Code) {
|
| err := fmt.Errorf("Found preprocessor macro in code.")
|
| - reportError(w, r, err, "Preprocessor macros aren't allowed.")
|
| + reportTryError(w, r, err, "Preprocessor macros aren't allowed.", "")
|
| return
|
| }
|
| hash, err := expandCode(LineNumbers(request.Code))
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to write the code to compile.")
|
| + reportTryError(w, r, err, "Failed to write the code to compile.", hash)
|
| return
|
| }
|
| writeToDatabase(hash, request.Code, request.Name)
|
| message, err := doCmd(fmt.Sprintf(RESULT_COMPILE, hash, hash), true)
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to compile the code:\n"+message)
|
| + message = cleanCompileOutput(message, hash)
|
| + reportTryError(w, r, err, message, hash)
|
| return
|
| }
|
| linkMessage, err := doCmd(fmt.Sprintf(LINK, hash, hash), true)
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to link the code:\n"+linkMessage)
|
| + linkMessage = cleanCompileOutput(linkMessage, hash)
|
| + reportTryError(w, r, err, linkMessage, hash)
|
| return
|
| }
|
| message += linkMessage
|
| @@ -609,7 +628,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
|
| } else {
|
| abs, err := filepath.Abs("../../../inout")
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to find executable directory.")
|
| + reportTryError(w, r, err, "Failed to find executable directory.", hash)
|
| return
|
| }
|
| cmd = abs + "/" + cmd
|
| @@ -617,23 +636,24 @@ func mainHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
| execMessage, err := doCmd(cmd, false)
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to run the code:\n"+execMessage)
|
| + reportTryError(w, r, err, "Failed to run the code:\n"+execMessage, hash)
|
| return
|
| }
|
| png, err := ioutil.ReadFile("../../../inout/" + hash + ".png")
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to open the generated PNG.")
|
| + reportTryError(w, r, err, "Failed to open the generated PNG.", hash)
|
| return
|
| }
|
|
|
| m := response{
|
| Message: message,
|
| + StdOut: execMessage,
|
| Img: base64.StdEncoding.EncodeToString([]byte(png)),
|
| Hash: hash,
|
| }
|
| resp, err := json.Marshal(m)
|
| if err != nil {
|
| - reportError(w, r, err, "Failed to serialize a response.")
|
| + reportTryError(w, r, err, "Failed to serialize a response.", hash)
|
| return
|
| }
|
| w.Write(resp)
|
|
|