| OLD | NEW |
| 1 package main | 1 package main |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "bytes" | 4 "bytes" |
| 5 "crypto/md5" | 5 "crypto/md5" |
| 6 "database/sql" | 6 "database/sql" |
| 7 "encoding/base64" | 7 "encoding/base64" |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "flag" | 9 "flag" |
| 10 "fmt" | 10 "fmt" |
| 11 _ "github.com/go-sql-driver/mysql" | |
| 12 _ "github.com/mattn/go-sqlite3" | |
| 13 htemplate "html/template" | 11 htemplate "html/template" |
| 14 "io/ioutil" | 12 "io/ioutil" |
| 15 "log" | 13 "log" |
| 16 "math/rand" | 14 "math/rand" |
| 17 "net/http" | 15 "net/http" |
| 18 "os" | 16 "os" |
| 19 "os/exec" | 17 "os/exec" |
| 20 "path/filepath" | 18 "path/filepath" |
| 21 "regexp" | 19 "regexp" |
| 22 "strings" | 20 "strings" |
| 23 "text/template" | 21 "text/template" |
| 24 "time" | 22 "time" |
| 25 ) | 23 ) |
| 26 | 24 |
| 25 import ( |
| 26 "github.com/fiorix/go-web/autogzip" |
| 27 _ "github.com/go-sql-driver/mysql" |
| 28 _ "github.com/mattn/go-sqlite3" |
| 29 ) |
| 30 |
| 27 const ( | 31 const ( |
| 28 RESULT_COMPILE = `../../experimental/webtry/safec++ -DSK_GAMMA_SRGB -DSK
_GAMMA_APPLY_TO_A8 -DSK_SCALAR_TO_FLOAT_EXCLUDED -DSK_ALLOW_STATIC_GLOBAL_INITIA
LIZERS=1 -DSK_SUPPORT_GPU=0 -DSK_SUPPORT_OPENCL=0 -DSK_FORCE_DISTANCEFIELD_FONTS
=0 -DSK_SCALAR_IS_FLOAT -DSK_CAN_USE_FLOAT -DSK_SAMPLES_FOR_X -DSK_BUILD_FOR_UNI
X -DSK_USE_POSIX_THREADS -DSK_SYSTEM_ZLIB=1 -DSK_DEBUG -DSK_DEVELOPER=1 -I../../
src/core -I../../src/images -I../../tools/flags -I../../include/config -I../../i
nclude/core -I../../include/pathops -I../../include/pipe -I../../include/effects
-I../../include/ports -I../../src/sfnt -I../../include/utils -I../../src/utils
-I../../include/images -g -fno-exceptions -fstrict-aliasing -Wall -Wextra -Winit
-self -Wpointer-arith -Wno-unused-parameter -m64 -fno-rtti -Wnon-virtual-dtor -c
../../../cache/%s.cpp -o ../../../cache/%s.o` | 32 RESULT_COMPILE = `../../experimental/webtry/safec++ -DSK_GAMMA_SRGB -DSK
_GAMMA_APPLY_TO_A8 -DSK_SCALAR_TO_FLOAT_EXCLUDED -DSK_ALLOW_STATIC_GLOBAL_INITIA
LIZERS=1 -DSK_SUPPORT_GPU=0 -DSK_SUPPORT_OPENCL=0 -DSK_FORCE_DISTANCEFIELD_FONTS
=0 -DSK_SCALAR_IS_FLOAT -DSK_CAN_USE_FLOAT -DSK_SAMPLES_FOR_X -DSK_BUILD_FOR_UNI
X -DSK_USE_POSIX_THREADS -DSK_SYSTEM_ZLIB=1 -DSK_DEBUG -DSK_DEVELOPER=1 -I../../
src/core -I../../src/images -I../../tools/flags -I../../include/config -I../../i
nclude/core -I../../include/pathops -I../../include/pipe -I../../include/effects
-I../../include/ports -I../../src/sfnt -I../../include/utils -I../../src/utils
-I../../include/images -g -fno-exceptions -fstrict-aliasing -Wall -Wextra -Winit
-self -Wpointer-arith -Wno-unused-parameter -m64 -fno-rtti -Wnon-virtual-dtor -c
../../../cache/%s.cpp -o ../../../cache/%s.o` |
| 29 LINK = `../../experimental/webtry/safec++ -m64 -lstdc++ -lm -o
../../../inout/%s -Wl,--start-group ../../../cache/%s.o obj/experimental/webtry
/webtry.main.o obj/gyp/libflags.a libskia_images.a libskia_core.a libskia_effect
s.a obj/gyp/libjpeg.a obj/gyp/libwebp_dec.a obj/gyp/libwebp_demux.a obj/gyp/libw
ebp_dsp.a obj/gyp/libwebp_enc.a obj/gyp/libwebp_utils.a libskia_utils.a libskia_
opts.a libskia_opts_ssse3.a libskia_ports.a libskia_sfnt.a -Wl,--end-group -lpng
-lz -lgif -lpthread -lfontconfig -ldl -lfreetype` | 33 LINK = `../../experimental/webtry/safec++ -m64 -lstdc++ -lm -o
../../../inout/%s -Wl,--start-group ../../../cache/%s.o obj/experimental/webtry
/webtry.main.o obj/gyp/libflags.a libskia_images.a libskia_core.a libskia_effect
s.a obj/gyp/libjpeg.a obj/gyp/libwebp_dec.a obj/gyp/libwebp_demux.a obj/gyp/libw
ebp_dsp.a obj/gyp/libwebp_enc.a obj/gyp/libwebp_utils.a libskia_utils.a libskia_
opts.a libskia_opts_ssse3.a libskia_ports.a libskia_sfnt.a -Wl,--end-group -lpng
-lz -lgif -lpthread -lfontconfig -ldl -lfreetype` |
| 30 DEFAULT_SAMPLE = `void draw(SkCanvas* canvas) { | 34 DEFAULT_SAMPLE = `void draw(SkCanvas* canvas) { |
| 31 SkPaint p; | 35 SkPaint p; |
| 32 p.setColor(SK_ColorRED); | 36 p.setColor(SK_ColorRED); |
| 33 p.setAntiAlias(true); | 37 p.setAntiAlias(true); |
| 34 p.setStyle(SkPaint::kStroke_Style); | 38 p.setStyle(SkPaint::kStroke_Style); |
| 35 p.setStrokeWidth(10); | 39 p.setStrokeWidth(10); |
| 36 | 40 |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 if err != nil { | 325 if err != nil { |
| 322 log.Printf("Exit status: %s\n", err.Error()) | 326 log.Printf("Exit status: %s\n", err.Error()) |
| 323 return string(message), fmt.Errorf("Failed to run command.") | 327 return string(message), fmt.Errorf("Failed to run command.") |
| 324 } | 328 } |
| 325 return string(message), nil | 329 return string(message), nil |
| 326 } | 330 } |
| 327 | 331 |
| 328 // reportError formats an HTTP error response and also logs the detailed error m
essage. | 332 // reportError formats an HTTP error response and also logs the detailed error m
essage. |
| 329 func reportError(w http.ResponseWriter, r *http.Request, err error, message stri
ng) { | 333 func reportError(w http.ResponseWriter, r *http.Request, err error, message stri
ng) { |
| 330 log.Printf("Error: %s\n%s", message, err.Error()) | 334 log.Printf("Error: %s\n%s", message, err.Error()) |
| 335 w.Header().Set("Content-Type", "text/plain") |
| 331 http.Error(w, message, 500) | 336 http.Error(w, message, 500) |
| 332 } | 337 } |
| 333 | 338 |
| 334 // reportTryError formats an HTTP error response in JSON and also logs the detai
led error message. | 339 // reportTryError formats an HTTP error response in JSON and also logs the detai
led error message. |
| 335 func reportTryError(w http.ResponseWriter, r *http.Request, err error, message,
hash string) { | 340 func reportTryError(w http.ResponseWriter, r *http.Request, err error, message,
hash string) { |
| 336 m := response{ | 341 m := response{ |
| 337 Message: message, | 342 Message: message, |
| 338 Hash: hash, | 343 Hash: hash, |
| 339 } | 344 } |
| 340 log.Printf("Error: %s\n%s", message, err.Error()) | 345 log.Printf("Error: %s\n%s", message, err.Error()) |
| 341 resp, err := json.Marshal(m) | 346 resp, err := json.Marshal(m) |
| 342 if err != nil { | 347 if err != nil { |
| 343 http.Error(w, "Failed to serialize a response", 500) | 348 http.Error(w, "Failed to serialize a response", 500) |
| 344 return | 349 return |
| 345 } | 350 } |
| 351 w.Header().Set("Content-Type", "text/plain") |
| 346 w.Write(resp) | 352 w.Write(resp) |
| 347 } | 353 } |
| 348 | 354 |
| 349 func writeToDatabase(hash string, code string, workspaceName string) { | 355 func writeToDatabase(hash string, code string, workspaceName string) { |
| 350 if db == nil { | 356 if db == nil { |
| 351 return | 357 return |
| 352 } | 358 } |
| 353 if _, err := db.Exec("INSERT INTO webtry (code, hash) VALUES(?, ?)", cod
e, hash); err != nil { | 359 if _, err := db.Exec("INSERT INTO webtry (code, hash) VALUES(?, ?)", cod
e, hash); err != nil { |
| 354 log.Printf("ERROR: Failed to insert code into database: %q\n", e
rr) | 360 log.Printf("ERROR: Failed to insert code into database: %q\n", e
rr) |
| 355 } | 361 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 366 if r.Method != "GET" { | 372 if r.Method != "GET" { |
| 367 http.NotFound(w, r) | 373 http.NotFound(w, r) |
| 368 return | 374 return |
| 369 } | 375 } |
| 370 match := imageLink.FindStringSubmatch(r.URL.Path) | 376 match := imageLink.FindStringSubmatch(r.URL.Path) |
| 371 if len(match) != 2 { | 377 if len(match) != 2 { |
| 372 http.NotFound(w, r) | 378 http.NotFound(w, r) |
| 373 return | 379 return |
| 374 } | 380 } |
| 375 filename := match[1] | 381 filename := match[1] |
| 382 w.Header().Set("Content-Type", "image/png") |
| 376 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) | 383 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) |
| 377 } | 384 } |
| 378 | 385 |
| 379 type Try struct { | 386 type Try struct { |
| 380 Hash string `json:"hash"` | 387 Hash string `json:"hash"` |
| 381 CreateTS string `json:"create_ts"` | 388 CreateTS string `json:"create_ts"` |
| 382 } | 389 } |
| 383 | 390 |
| 384 type Recent struct { | 391 type Recent struct { |
| 385 Tries []Try | 392 Tries []Try |
| (...skipping 13 matching lines...) Expand all Loading... |
| 399 recent := []Try{} | 406 recent := []Try{} |
| 400 for rows.Next() { | 407 for rows.Next() { |
| 401 var hash string | 408 var hash string |
| 402 var create_ts time.Time | 409 var create_ts time.Time |
| 403 if err := rows.Scan(&create_ts, &hash); err != nil { | 410 if err := rows.Scan(&create_ts, &hash); err != nil { |
| 404 log.Printf("Error: failed to fetch from database: %q", e
rr) | 411 log.Printf("Error: failed to fetch from database: %q", e
rr) |
| 405 continue | 412 continue |
| 406 } | 413 } |
| 407 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form
at("2006-02-01")}) | 414 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form
at("2006-02-01")}) |
| 408 } | 415 } |
| 416 w.Header().Set("Content-Type", "text/html") |
| 409 if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titl
ebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { | 417 if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titl
ebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
| 410 log.Printf("ERROR: Failed to expand template: %q\n", err) | 418 log.Printf("ERROR: Failed to expand template: %q\n", err) |
| 411 } | 419 } |
| 412 } | 420 } |
| 413 | 421 |
| 414 type Workspace struct { | 422 type Workspace struct { |
| 415 Name string | 423 Name string |
| 416 Code string | 424 Code string |
| 417 Hash string | 425 Hash string |
| 418 Tries []Try | 426 Tries []Try |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 } | 477 } |
| 470 } | 478 } |
| 471 var code string | 479 var code string |
| 472 var hash string | 480 var hash string |
| 473 if len(tries) == 0 { | 481 if len(tries) == 0 { |
| 474 code = DEFAULT_SAMPLE | 482 code = DEFAULT_SAMPLE |
| 475 } else { | 483 } else { |
| 476 hash = tries[len(tries)-1].Hash | 484 hash = tries[len(tries)-1].Hash |
| 477 code, _ = getCode(hash) | 485 code, _ = getCode(hash) |
| 478 } | 486 } |
| 487 w.Header().Set("Content-Type", "text/html") |
| 479 if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C
ode: code, Name: name, Hash: hash, Titlebar: Titlebar{GitHash: gitHash, GitInfo:
gitInfo}}); err != nil { | 488 if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C
ode: code, Name: name, Hash: hash, Titlebar: Titlebar{GitHash: gitHash, GitInfo:
gitInfo}}); err != nil { |
| 480 log.Printf("ERROR: Failed to expand template: %q\n", err
) | 489 log.Printf("ERROR: Failed to expand template: %q\n", err
) |
| 481 } | 490 } |
| 482 } else if r.Method == "POST" { | 491 } else if r.Method == "POST" { |
| 483 name, err := newWorkspace() | 492 name, err := newWorkspace() |
| 484 if err != nil { | 493 if err != nil { |
| 485 http.Error(w, "Failed to create a new workspace.", 500) | 494 http.Error(w, "Failed to create a new workspace.", 500) |
| 486 return | 495 return |
| 487 } | 496 } |
| 488 http.Redirect(w, r, "/w/"+name, 302) | 497 http.Redirect(w, r, "/w/"+name, 302) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 http.NotFound(w, r) | 531 http.NotFound(w, r) |
| 523 return | 532 return |
| 524 } | 533 } |
| 525 var code string | 534 var code string |
| 526 code, err := getCode(hash) | 535 code, err := getCode(hash) |
| 527 if err != nil { | 536 if err != nil { |
| 528 http.NotFound(w, r) | 537 http.NotFound(w, r) |
| 529 return | 538 return |
| 530 } | 539 } |
| 531 // Expand the template. | 540 // Expand the template. |
| 541 w.Header().Set("Content-Type", "text/html") |
| 532 if err := iframeTemplate.Execute(w, userCode{Code: code, Hash: hash}); e
rr != nil { | 542 if err := iframeTemplate.Execute(w, userCode{Code: code, Hash: hash}); e
rr != nil { |
| 533 log.Printf("ERROR: Failed to expand template: %q\n", err) | 543 log.Printf("ERROR: Failed to expand template: %q\n", err) |
| 534 } | 544 } |
| 535 } | 545 } |
| 536 | 546 |
| 537 type TryInfo struct { | 547 type TryInfo struct { |
| 538 Hash string `json:"hash"` | 548 Hash string `json:"hash"` |
| 539 Code string `json:"code"` | 549 Code string `json:"code"` |
| 540 } | 550 } |
| 541 | 551 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 http.NotFound(w, r) | 599 http.NotFound(w, r) |
| 590 return | 600 return |
| 591 } | 601 } |
| 592 // Update 'code' with the code found in the database. | 602 // Update 'code' with the code found in the database. |
| 593 if err := db.QueryRow("SELECT code FROM webtry WHERE has
h=?", hash).Scan(&code); err != nil { | 603 if err := db.QueryRow("SELECT code FROM webtry WHERE has
h=?", hash).Scan(&code); err != nil { |
| 594 http.NotFound(w, r) | 604 http.NotFound(w, r) |
| 595 return | 605 return |
| 596 } | 606 } |
| 597 } | 607 } |
| 598 // Expand the template. | 608 // Expand the template. |
| 609 w.Header().Set("Content-Type", "text/html") |
| 599 if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha
sh, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { | 610 if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha
sh, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
| 600 log.Printf("ERROR: Failed to expand template: %q\n", err
) | 611 log.Printf("ERROR: Failed to expand template: %q\n", err
) |
| 601 } | 612 } |
| 602 } else if r.Method == "POST" { | 613 } else if r.Method == "POST" { |
| 603 w.Header().Set("Content-Type", "application/json") | 614 w.Header().Set("Content-Type", "application/json") |
| 604 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) | 615 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) |
| 605 n, err := buf.ReadFrom(r.Body) | 616 n, err := buf.ReadFrom(r.Body) |
| 606 if err != nil { | 617 if err != nil { |
| 607 reportTryError(w, r, err, "Failed to read a request body
.", "") | 618 reportTryError(w, r, err, "Failed to read a request body
.", "") |
| 608 return | 619 return |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 Message: message, | 679 Message: message, |
| 669 StdOut: execMessage, | 680 StdOut: execMessage, |
| 670 Img: base64.StdEncoding.EncodeToString([]byte(png)), | 681 Img: base64.StdEncoding.EncodeToString([]byte(png)), |
| 671 Hash: hash, | 682 Hash: hash, |
| 672 } | 683 } |
| 673 resp, err := json.Marshal(m) | 684 resp, err := json.Marshal(m) |
| 674 if err != nil { | 685 if err != nil { |
| 675 reportTryError(w, r, err, "Failed to serialize a respons
e.", hash) | 686 reportTryError(w, r, err, "Failed to serialize a respons
e.", hash) |
| 676 return | 687 return |
| 677 } | 688 } |
| 689 w.Header().Set("Content-Type", "application/json") |
| 678 w.Write(resp) | 690 w.Write(resp) |
| 679 } | 691 } |
| 680 } | 692 } |
| 681 | 693 |
| 682 func main() { | 694 func main() { |
| 683 flag.Parse() | 695 flag.Parse() |
| 684 » http.HandleFunc("/i/", imageHandler) | 696 » http.HandleFunc("/i/", autogzip.HandleFunc(imageHandler)) |
| 685 » http.HandleFunc("/w/", workspaceHandler) | 697 » http.HandleFunc("/w/", autogzip.HandleFunc(workspaceHandler)) |
| 686 » http.HandleFunc("/recent/", recentHandler) | 698 » http.HandleFunc("/recent/", autogzip.HandleFunc(recentHandler)) |
| 687 » http.HandleFunc("/iframe/", iframeHandler) | 699 » http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler)) |
| 688 » http.HandleFunc("/json/", tryInfoHandler) | 700 » http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler)) |
| 689 | 701 |
| 690 // Resources are served directly | 702 // Resources are served directly |
| 691 // TODO add support for caching/etags/gzip | 703 // TODO add support for caching/etags/gzip |
| 692 » http.Handle("/res/", http.FileServer(http.Dir("./"))) | 704 » http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./")))) |
| 693 | 705 |
| 694 // TODO Break out /c/ as it's own handler. | 706 // TODO Break out /c/ as it's own handler. |
| 695 » http.HandleFunc("/", mainHandler) | 707 » http.HandleFunc("/", autogzip.HandleFunc(mainHandler)) |
| 696 log.Fatal(http.ListenAndServe(*port, nil)) | 708 log.Fatal(http.ListenAndServe(*port, nil)) |
| 697 } | 709 } |
| OLD | NEW |