Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: experimental/webtry/webtry.go

Issue 246393002: Adding the ability to click on the images in the history and have that load (Closed) Base URL: https://skia.googlesource.com/skia.git@history
Patch Set: remove old logging code Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « experimental/webtry/templates/workspace.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 // directLink is the regex that matches URLs paths that are direct links . 61 // directLink is the regex that matches URLs paths that are direct links .
62 directLink = regexp.MustCompile("^/c/([a-f0-9]+)$") 62 directLink = regexp.MustCompile("^/c/([a-f0-9]+)$")
63 63
64 // iframeLink is the regex that matches URLs paths that are links to ifr ames. 64 // iframeLink is the regex that matches URLs paths that are links to ifr ames.
65 iframeLink = regexp.MustCompile("^/iframe/([a-f0-9]+)$") 65 iframeLink = regexp.MustCompile("^/iframe/([a-f0-9]+)$")
66 66
67 // imageLink is the regex that matches URLs paths that are direct links to PNGs. 67 // imageLink is the regex that matches URLs paths that are direct links to PNGs.
68 imageLink = regexp.MustCompile("^/i/([a-f0-9]+.png)$") 68 imageLink = regexp.MustCompile("^/i/([a-f0-9]+.png)$")
69 69
70 // tryInfoLink is the regex that matches URLs paths that are direct link s to data about a single try.
71 tryInfoLink = regexp.MustCompile("^/json/([a-f0-9]+)$")
72
70 // workspaceLink is the regex that matches URLs paths for workspaces. 73 // workspaceLink is the regex that matches URLs paths for workspaces.
71 workspaceLink = regexp.MustCompile("^/w/([a-z0-9-]+)$") 74 workspaceLink = regexp.MustCompile("^/w/([a-z0-9-]+)$")
72 75
73 // workspaceNameAdj is a list of adjectives for building workspace names . 76 // workspaceNameAdj is a list of adjectives for building workspace names .
74 workspaceNameAdj = []string{ 77 workspaceNameAdj = []string{
75 "autumn", "hidden", "bitter", "misty", "silent", "empty", "dry", "dark", 78 "autumn", "hidden", "bitter", "misty", "silent", "empty", "dry", "dark",
76 "summer", "icy", "delicate", "quiet", "white", "cool", "spring", "winter", 79 "summer", "icy", "delicate", "quiet", "white", "cool", "spring", "winter",
77 "patient", "twilight", "dawn", "crimson", "wispy", "weathered", "blue", 80 "patient", "twilight", "dawn", "crimson", "wispy", "weathered", "blue",
78 "billowing", "broken", "cold", "damp", "falling", "frosty", "gre en", 81 "billowing", "broken", "cold", "damp", "falling", "frosty", "gre en",
79 "long", "late", "lingering", "bold", "little", "morning", "muddy ", "old", 82 "long", "late", "lingering", "bold", "little", "morning", "muddy ", "old",
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form at("2006-02-01")}) 378 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form at("2006-02-01")})
376 } 379 }
377 if err := recentTemplate.Execute(w, Recent{Tries: recent}); err != nil { 380 if err := recentTemplate.Execute(w, Recent{Tries: recent}); err != nil {
378 log.Printf("ERROR: Failed to expand template: %q\n", err) 381 log.Printf("ERROR: Failed to expand template: %q\n", err)
379 } 382 }
380 } 383 }
381 384
382 type Workspace struct { 385 type Workspace struct {
383 Name string 386 Name string
384 Code string 387 Code string
388 Hash string
385 Tries []Try 389 Tries []Try
386 } 390 }
387 391
388 // newWorkspace generates a new random workspace name and stores it in the datab ase. 392 // newWorkspace generates a new random workspace name and stores it in the datab ase.
389 func newWorkspace() (string, error) { 393 func newWorkspace() (string, error) {
390 for i := 0; i < 10; i++ { 394 for i := 0; i < 10; i++ {
391 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))] 395 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))]
392 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))] 396 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))]
393 suffix := rand.Intn(1000) 397 suffix := rand.Intn(1000)
394 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix) 398 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix)
395 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n ame); err == nil { 399 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n ame); err == nil {
396 return name, nil 400 return name, nil
397 } else { 401 } else {
398 log.Printf("ERROR: Failed to insert workspace into datab ase: %q\n", err) 402 log.Printf("ERROR: Failed to insert workspace into datab ase: %q\n", err)
399 } 403 }
400 } 404 }
401 return "", fmt.Errorf("Failed to create a new workspace") 405 return "", fmt.Errorf("Failed to create a new workspace")
402 } 406 }
403 407
404 // getCode returns the code for a given hash, or the empty string if not found. 408 // getCode returns the code for a given hash, or the empty string if not found.
405 func getCode(hash string) string { 409 func getCode(hash string) (string, error) {
406 code := "" 410 code := ""
407 if err := db.QueryRow("SELECT code FROM webtry WHERE hash=?", hash).Scan (&code); err != nil { 411 if err := db.QueryRow("SELECT code FROM webtry WHERE hash=?", hash).Scan (&code); err != nil {
408 log.Printf("ERROR: Code for hash is missing: %q\n", err) 412 log.Printf("ERROR: Code for hash is missing: %q\n", err)
413 return code, err
409 } 414 }
410 » return code 415 » return code, nil
411 } 416 }
412 417
413 func workspaceHandler(w http.ResponseWriter, r *http.Request) { 418 func workspaceHandler(w http.ResponseWriter, r *http.Request) {
414 log.Printf("Workspace Handler: %q\n", r.URL.Path) 419 log.Printf("Workspace Handler: %q\n", r.URL.Path)
415 if r.Method == "GET" { 420 if r.Method == "GET" {
416 tries := []Try{} 421 tries := []Try{}
417 match := workspaceLink.FindStringSubmatch(r.URL.Path) 422 match := workspaceLink.FindStringSubmatch(r.URL.Path)
418 name := "" 423 name := ""
419 if len(match) == 2 { 424 if len(match) == 2 {
420 name = match[1] 425 name = match[1]
421 rows, err := db.Query("SELECT create_ts, hash FROM works pacetry WHERE name=? ORDER BY create_ts", name) 426 rows, err := db.Query("SELECT create_ts, hash FROM works pacetry WHERE name=? ORDER BY create_ts", name)
422 if err != nil { 427 if err != nil {
423 reportError(w, r, err, "Failed to select.") 428 reportError(w, r, err, "Failed to select.")
424 return 429 return
425 } 430 }
426 for rows.Next() { 431 for rows.Next() {
427 var hash string 432 var hash string
428 var create_ts time.Time 433 var create_ts time.Time
429 if err := rows.Scan(&create_ts, &hash); err != n il { 434 if err := rows.Scan(&create_ts, &hash); err != n il {
430 log.Printf("Error: failed to fetch from database: %q", err) 435 log.Printf("Error: failed to fetch from database: %q", err)
431 continue 436 continue
432 } 437 }
433 tries = append(tries, Try{Hash: hash, CreateTS: create_ts.Format("2006-02-01")}) 438 tries = append(tries, Try{Hash: hash, CreateTS: create_ts.Format("2006-02-01")})
434 } 439 }
435 } 440 }
436 var code string 441 var code string
442 var hash string
437 if len(tries) == 0 { 443 if len(tries) == 0 {
438 code = DEFAULT_SAMPLE 444 code = DEFAULT_SAMPLE
439 } else { 445 } else {
440 » » » code = getCode(tries[len(tries)-1].Hash) 446 » » » hash = tries[len(tries)-1].Hash
447 » » » code, _ = getCode(hash)
441 } 448 }
442 » » if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C ode: code, Name: name}); err != nil { 449 » » if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C ode: code, Name: name, Hash: hash}); err != nil {
443 log.Printf("ERROR: Failed to expand template: %q\n", err ) 450 log.Printf("ERROR: Failed to expand template: %q\n", err )
444 } 451 }
445 } else if r.Method == "POST" { 452 } else if r.Method == "POST" {
446 name, err := newWorkspace() 453 name, err := newWorkspace()
447 if err != nil { 454 if err != nil {
448 http.Error(w, "Failed to create a new workspace.", 500) 455 http.Error(w, "Failed to create a new workspace.", 500)
449 return 456 return
450 } 457 }
451 http.Redirect(w, r, "/w/"+name, 302) 458 http.Redirect(w, r, "/w/"+name, 302)
452 } 459 }
453 } 460 }
454 461
455 // hasPreProcessor returns true if any line in the code begins with a # char. 462 // hasPreProcessor returns true if any line in the code begins with a # char.
456 func hasPreProcessor(code string) bool { 463 func hasPreProcessor(code string) bool {
457 lines := strings.Split(code, "\n") 464 lines := strings.Split(code, "\n")
458 for _, s := range lines { 465 for _, s := range lines {
459 if strings.HasPrefix(strings.TrimSpace(s), "#") { 466 if strings.HasPrefix(strings.TrimSpace(s), "#") {
460 return true 467 return true
461 } 468 }
462 } 469 }
463 return false 470 return false
464 } 471 }
465 472
466 type TryRequest struct { 473 type TryRequest struct {
467 Code string `json:"code"` 474 Code string `json:"code"`
468 » Name string `json:"name"` 475 » Name string `json:"name"` // Optional name of the workspace the code is in.
469 } 476 }
470 477
471 // iframeHandler handles the GET and POST of the main page. 478 // iframeHandler handles the GET and POST of the main page.
472 func iframeHandler(w http.ResponseWriter, r *http.Request) { 479 func iframeHandler(w http.ResponseWriter, r *http.Request) {
473 log.Printf("IFrame Handler: %q\n", r.URL.Path) 480 log.Printf("IFrame Handler: %q\n", r.URL.Path)
474 if r.Method != "GET" { 481 if r.Method != "GET" {
475 http.NotFound(w, r) 482 http.NotFound(w, r)
476 return 483 return
477 } 484 }
478 match := iframeLink.FindStringSubmatch(r.URL.Path) 485 match := iframeLink.FindStringSubmatch(r.URL.Path)
479 if len(match) != 2 { 486 if len(match) != 2 {
480 http.NotFound(w, r) 487 http.NotFound(w, r)
481 return 488 return
482 } 489 }
483 hash := match[1] 490 hash := match[1]
484 if db == nil { 491 if db == nil {
485 http.NotFound(w, r) 492 http.NotFound(w, r)
486 return 493 return
487 } 494 }
488 var code string 495 var code string
489 » // Load 'code' with the code found in the database. 496 » code, err := getCode(hash)
490 » if err := db.QueryRow("SELECT code FROM webtry WHERE hash=?", hash).Scan (&code); err != nil { 497 » if err != nil {
491 http.NotFound(w, r) 498 http.NotFound(w, r)
492 return 499 return
493 } 500 }
494 // Expand the template. 501 // Expand the template.
495 if err := iframeTemplate.Execute(w, userCode{UserCode: code, Hash: hash} ); err != nil { 502 if err := iframeTemplate.Execute(w, userCode{UserCode: code, Hash: hash} ); err != nil {
496 log.Printf("ERROR: Failed to expand template: %q\n", err) 503 log.Printf("ERROR: Failed to expand template: %q\n", err)
497 } 504 }
498 } 505 }
499 506
507 type TryInfo struct {
508 Hash string `json:"hash"`
509 Code string `json:"code"`
510 }
511
512 // tryInfoHandler returns information about a specific try.
513 func tryInfoHandler(w http.ResponseWriter, r *http.Request) {
514 log.Printf("Try Info Handler: %q\n", r.URL.Path)
515 if r.Method != "GET" {
516 http.NotFound(w, r)
517 return
518 }
519 match := tryInfoLink.FindStringSubmatch(r.URL.Path)
520 if len(match) != 2 {
521 http.NotFound(w, r)
522 return
523 }
524 hash := match[1]
525 code, err := getCode(hash)
526 if err != nil {
527 http.NotFound(w, r)
528 return
529 }
530 m := TryInfo{
531 Hash: hash,
532 Code: code,
533 }
534 resp, err := json.Marshal(m)
535 if err != nil {
536 reportError(w, r, err, "Failed to serialize a response.")
537 return
538 }
539 w.Header().Set("Content-Type", "application/json")
540 w.Write(resp)
541 }
542
500 // mainHandler handles the GET and POST of the main page. 543 // mainHandler handles the GET and POST of the main page.
501 func mainHandler(w http.ResponseWriter, r *http.Request) { 544 func mainHandler(w http.ResponseWriter, r *http.Request) {
502 log.Printf("Main Handler: %q\n", r.URL.Path) 545 log.Printf("Main Handler: %q\n", r.URL.Path)
503 if r.Method == "GET" { 546 if r.Method == "GET" {
504 code := DEFAULT_SAMPLE 547 code := DEFAULT_SAMPLE
505 match := directLink.FindStringSubmatch(r.URL.Path) 548 match := directLink.FindStringSubmatch(r.URL.Path)
549 var hash string
506 if len(match) == 2 && r.URL.Path != "/" { 550 if len(match) == 2 && r.URL.Path != "/" {
507 » » » hash := match[1] 551 » » » hash = match[1]
508 if db == nil { 552 if db == nil {
509 http.NotFound(w, r) 553 http.NotFound(w, r)
510 return 554 return
511 } 555 }
512 // Update 'code' with the code found in the database. 556 // Update 'code' with the code found in the database.
513 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil { 557 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil {
514 http.NotFound(w, r) 558 http.NotFound(w, r)
515 return 559 return
516 } 560 }
517 } 561 }
518 // Expand the template. 562 // Expand the template.
519 » » if err := indexTemplate.Execute(w, userCode{UserCode: code}); er r != nil { 563 » » if err := indexTemplate.Execute(w, userCode{UserCode: code, Hash : hash}); err != nil {
520 log.Printf("ERROR: Failed to expand template: %q\n", err ) 564 log.Printf("ERROR: Failed to expand template: %q\n", err )
521 } 565 }
522 } else if r.Method == "POST" { 566 } else if r.Method == "POST" {
523 w.Header().Set("Content-Type", "application/json") 567 w.Header().Set("Content-Type", "application/json")
524 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) 568 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE))
525 n, err := buf.ReadFrom(r.Body) 569 n, err := buf.ReadFrom(r.Body)
526 if err != nil { 570 if err != nil {
527 reportError(w, r, err, "Failed to read a request body.") 571 reportError(w, r, err, "Failed to read a request body.")
528 return 572 return
529 } 573 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 w.Write(resp) 639 w.Write(resp)
596 } 640 }
597 } 641 }
598 642
599 func main() { 643 func main() {
600 flag.Parse() 644 flag.Parse()
601 http.HandleFunc("/i/", imageHandler) 645 http.HandleFunc("/i/", imageHandler)
602 http.HandleFunc("/w/", workspaceHandler) 646 http.HandleFunc("/w/", workspaceHandler)
603 http.HandleFunc("/recent/", recentHandler) 647 http.HandleFunc("/recent/", recentHandler)
604 http.HandleFunc("/iframe/", iframeHandler) 648 http.HandleFunc("/iframe/", iframeHandler)
649 http.HandleFunc("/json/", tryInfoHandler)
605 http.HandleFunc("/css/", cssHandler) 650 http.HandleFunc("/css/", cssHandler)
606 http.HandleFunc("/js/", jsHandler) 651 http.HandleFunc("/js/", jsHandler)
652 // TODO Break out /c/ as it's own handler.
607 http.HandleFunc("/", mainHandler) 653 http.HandleFunc("/", mainHandler)
608 log.Fatal(http.ListenAndServe(*port, nil)) 654 log.Fatal(http.ListenAndServe(*port, nil))
609 } 655 }
OLDNEW
« no previous file with comments | « experimental/webtry/templates/workspace.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698