| 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/binary" | 8 "encoding/binary" |
| 9 "encoding/json" | 9 "encoding/json" |
| 10 "flag" | 10 "flag" |
| 11 "fmt" | 11 "fmt" |
| 12 htemplate "html/template" | 12 htemplate "html/template" |
| 13 "image" | 13 "image" |
| 14 _ "image/gif" | 14 _ "image/gif" |
| 15 _ "image/jpeg" | 15 _ "image/jpeg" |
| 16 "image/png" | 16 "image/png" |
| 17 "io/ioutil" | 17 "io/ioutil" |
| 18 "log" | |
| 19 "math/rand" | 18 "math/rand" |
| 20 "net" | 19 "net" |
| 21 "net/http" | 20 "net/http" |
| 22 "os" | 21 "os" |
| 23 "os/exec" | 22 "os/exec" |
| 24 "path/filepath" | 23 "path/filepath" |
| 25 "regexp" | 24 "regexp" |
| 26 "strings" | 25 "strings" |
| 27 "text/template" | 26 "text/template" |
| 28 "time" | 27 "time" |
| 29 ) | 28 ) |
| 30 | 29 |
| 31 import ( | 30 import ( |
| 32 "github.com/fiorix/go-web/autogzip" | 31 "github.com/fiorix/go-web/autogzip" |
| 33 _ "github.com/go-sql-driver/mysql" | 32 _ "github.com/go-sql-driver/mysql" |
| 33 "github.com/golang/glog" |
| 34 _ "github.com/mattn/go-sqlite3" | 34 _ "github.com/mattn/go-sqlite3" |
| 35 "github.com/rcrowley/go-metrics" | 35 "github.com/rcrowley/go-metrics" |
| 36 ) | 36 ) |
| 37 | 37 |
| 38 const ( | 38 const ( |
| 39 DEFAULT_SAMPLE = `void draw(SkCanvas* canvas) { | 39 DEFAULT_SAMPLE = `void draw(SkCanvas* canvas) { |
| 40 SkPaint p; | 40 SkPaint p; |
| 41 p.setColor(SK_ColorRED); | 41 p.setColor(SK_ColorRED); |
| 42 p.setAntiAlias(true); | 42 p.setAntiAlias(true); |
| 43 p.setStyle(SkPaint::kStroke_Style); | 43 p.setStyle(SkPaint::kStroke_Style); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 return strings.Join(ret, "\n") | 135 return strings.Join(ret, "\n") |
| 136 } | 136 } |
| 137 | 137 |
| 138 func init() { | 138 func init() { |
| 139 rand.Seed(time.Now().UnixNano()) | 139 rand.Seed(time.Now().UnixNano()) |
| 140 | 140 |
| 141 // Change the current working directory to the directory of the executab
le. | 141 // Change the current working directory to the directory of the executab
le. |
| 142 var err error | 142 var err error |
| 143 cwd, err := filepath.Abs(filepath.Dir(os.Args[0])) | 143 cwd, err := filepath.Abs(filepath.Dir(os.Args[0])) |
| 144 if err != nil { | 144 if err != nil { |
| 145 » » log.Fatal(err) | 145 » » glog.Fatal(err) |
| 146 } | 146 } |
| 147 os.Chdir(cwd) | 147 os.Chdir(cwd) |
| 148 | 148 |
| 149 codeTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "tem
plates/template.cpp"))) | 149 codeTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "tem
plates/template.cpp"))) |
| 150 gypTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "temp
lates/template.gyp"))) | 150 gypTemplate = template.Must(template.ParseFiles(filepath.Join(cwd, "temp
lates/template.gyp"))) |
| 151 indexTemplate = htemplate.Must(htemplate.ParseFiles( | 151 indexTemplate = htemplate.Must(htemplate.ParseFiles( |
| 152 filepath.Join(cwd, "templates/index.html"), | 152 filepath.Join(cwd, "templates/index.html"), |
| 153 filepath.Join(cwd, "templates/titlebar.html"), | 153 filepath.Join(cwd, "templates/titlebar.html"), |
| 154 filepath.Join(cwd, "templates/sidebar.html"), | 154 filepath.Join(cwd, "templates/sidebar.html"), |
| 155 filepath.Join(cwd, "templates/content.html"), | 155 filepath.Join(cwd, "templates/content.html"), |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 // See https://developers.google.com/compute/docs/metadata#custom. | 194 // See https://developers.google.com/compute/docs/metadata#custom. |
| 195 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i
nstance/attributes/password", nil) | 195 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i
nstance/attributes/password", nil) |
| 196 if err != nil { | 196 if err != nil { |
| 197 panic(err) | 197 panic(err) |
| 198 } | 198 } |
| 199 client := http.Client{} | 199 client := http.Client{} |
| 200 req.Header.Add("X-Google-Metadata-Request", "True") | 200 req.Header.Add("X-Google-Metadata-Request", "True") |
| 201 if resp, err := client.Do(req); err == nil { | 201 if resp, err := client.Do(req); err == nil { |
| 202 password, err := ioutil.ReadAll(resp.Body) | 202 password, err := ioutil.ReadAll(resp.Body) |
| 203 if err != nil { | 203 if err != nil { |
| 204 » » » log.Printf("ERROR: Failed to read password from metadata
server: %q\n", err) | 204 » » » glog.Errorf("Failed to read password from metadata serve
r: %q\n", err) |
| 205 panic(err) | 205 panic(err) |
| 206 } | 206 } |
| 207 // The IP address of the database is found here: | 207 // The IP address of the database is found here: |
| 208 // https://console.developers.google.com/project/31977622648/
sql/instances/webtry/overview | 208 // https://console.developers.google.com/project/31977622648/
sql/instances/webtry/overview |
| 209 // And 3306 is the default port for MySQL. | 209 // And 3306 is the default port for MySQL. |
| 210 db, err = sql.Open("mysql", fmt.Sprintf("webtry:%s@tcp(173.194.8
3.52:3306)/webtry?parseTime=true", password)) | 210 db, err = sql.Open("mysql", fmt.Sprintf("webtry:%s@tcp(173.194.8
3.52:3306)/webtry?parseTime=true", password)) |
| 211 if err != nil { | 211 if err != nil { |
| 212 » » » log.Printf("ERROR: Failed to open connection to SQL serv
er: %q\n", err) | 212 » » » glog.Errorf("ERROR: Failed to open connection to SQL ser
ver: %q\n", err) |
| 213 panic(err) | 213 panic(err) |
| 214 } | 214 } |
| 215 } else { | 215 } else { |
| 216 » » log.Printf("INFO: Failed to find metadata, unable to connect to
MySQL server (Expected when running locally): %q\n", err) | 216 » » glog.Infof("Failed to find metadata, unable to connect to MySQL
server (Expected when running locally): %q\n", err) |
| 217 // Fallback to sqlite for local use. | 217 // Fallback to sqlite for local use. |
| 218 db, err = sql.Open("sqlite3", "./webtry.db") | 218 db, err = sql.Open("sqlite3", "./webtry.db") |
| 219 if err != nil { | 219 if err != nil { |
| 220 » » » log.Printf("ERROR: Failed to open: %q\n", err) | 220 » » » glog.Errorf("Failed to open: %q\n", err) |
| 221 panic(err) | 221 panic(err) |
| 222 } | 222 } |
| 223 sql := `CREATE TABLE IF NOT EXISTS source_images ( | 223 sql := `CREATE TABLE IF NOT EXISTS source_images ( |
| 224 id INTEGER PRIMARY KEY NOT NULL, | 224 id INTEGER PRIMARY KEY NOT NULL, |
| 225 image MEDIUMBLOB DEFAULT '' NOT NULL, -- forma
tted as a PNG. | 225 image MEDIUMBLOB DEFAULT '' NOT NULL, -- forma
tted as a PNG. |
| 226 width INTEGER DEFAULT 0 NOT NULL, | 226 width INTEGER DEFAULT 0 NOT NULL, |
| 227 height INTEGER DEFAULT 0 NOT NULL, | 227 height INTEGER DEFAULT 0 NOT NULL, |
| 228 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, | 228 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
| 229 hidden INTEGER DEFAULT 0 NOT NULL | 229 hidden INTEGER DEFAULT 0 NOT NULL |
| 230 )` | 230 )` |
| 231 _, err = db.Exec(sql) | 231 _, err = db.Exec(sql) |
| 232 if err != nil { | 232 if err != nil { |
| 233 » » » log.Printf("Info: status creating sqlite table for sourc
es: %q\n", err) | 233 » » » glog.Infof("status creating sqlite table for sources: %q
\n", err) |
| 234 } | 234 } |
| 235 | 235 |
| 236 sql = `CREATE TABLE IF NOT EXISTS webtry ( | 236 sql = `CREATE TABLE IF NOT EXISTS webtry ( |
| 237 code TEXT DEFAULT '' NOT NULL, | 237 code TEXT DEFAULT '' NOT NULL, |
| 238 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, | 238 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
| 239 hash CHAR(64) DEFAULT '' NOT NULL, | 239 hash CHAR(64) DEFAULT '' NOT NULL, |
| 240 width INTEGER DEFAULT 256 NOT NULL, | 240 width INTEGER DEFAULT 256 NOT NULL, |
| 241 height INTEGER DEFAULT 256 NOT NULL, | 241 height INTEGER DEFAULT 256 NOT NULL, |
| 242 gpu BOOL DEFAULT 0 NOT NULL, | 242 gpu BOOL DEFAULT 0 NOT NULL, |
| 243 source_image_id INTEGER DEFAULT 0 NOT NULL, | 243 source_image_id INTEGER DEFAULT 0 NOT NULL, |
| 244 | 244 |
| 245 PRIMARY KEY(hash) | 245 PRIMARY KEY(hash) |
| 246 )` | 246 )` |
| 247 _, err = db.Exec(sql) | 247 _, err = db.Exec(sql) |
| 248 if err != nil { | 248 if err != nil { |
| 249 » » » log.Printf("Info: status creating sqlite table for webtr
y: %q\n", err) | 249 » » » glog.Infof("status creating sqlite table for webtry: %q\
n", err) |
| 250 } | 250 } |
| 251 | 251 |
| 252 sql = `CREATE TABLE IF NOT EXISTS workspace ( | 252 sql = `CREATE TABLE IF NOT EXISTS workspace ( |
| 253 name CHAR(64) DEFAULT '' NOT NULL, | 253 name CHAR(64) DEFAULT '' NOT NULL, |
| 254 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, | 254 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
| 255 PRIMARY KEY(name) | 255 PRIMARY KEY(name) |
| 256 )` | 256 )` |
| 257 _, err = db.Exec(sql) | 257 _, err = db.Exec(sql) |
| 258 if err != nil { | 258 if err != nil { |
| 259 » » » log.Printf("Info: status creating sqlite table for works
pace: %q\n", err) | 259 » » » glog.Infof("status creating sqlite table for workspace:
%q\n", err) |
| 260 } | 260 } |
| 261 | 261 |
| 262 sql = `CREATE TABLE IF NOT EXISTS workspacetry ( | 262 sql = `CREATE TABLE IF NOT EXISTS workspacetry ( |
| 263 name CHAR(64) DEFAULT '' NOT NULL, | 263 name CHAR(64) DEFAULT '' NOT NULL, |
| 264 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, | 264 create_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, |
| 265 hash CHAR(64) DEFAULT '' NOT NULL, | 265 hash CHAR(64) DEFAULT '' NOT NULL, |
| 266 width INTEGER DEFAULT 256 NOT NULL, | 266 width INTEGER DEFAULT 256 NOT NULL, |
| 267 height INTEGER DEFAULT 256 NOT NULL, | 267 height INTEGER DEFAULT 256 NOT NULL, |
| 268 gpu BOOL DEFAULT 0 NOT NULL, | 268 gpu BOOL DEFAULT 0 NOT NULL, |
| 269 hidden INTEGER DEFAULT 0 NOT NULL, | 269 hidden INTEGER DEFAULT 0 NOT NULL, |
| 270 source_image_id INTEGER DEFAULT 0 NOT NULL, | 270 source_image_id INTEGER DEFAULT 0 NOT NULL, |
| 271 | 271 |
| 272 FOREIGN KEY (name) REFERENCES workspace(name) | 272 FOREIGN KEY (name) REFERENCES workspace(name) |
| 273 )` | 273 )` |
| 274 _, err = db.Exec(sql) | 274 _, err = db.Exec(sql) |
| 275 if err != nil { | 275 if err != nil { |
| 276 » » » log.Printf("Info: status creating sqlite table for works
pace try: %q\n", err) | 276 » » » glog.Infof("status creating sqlite table for workspace t
ry: %q\n", err) |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 | 279 |
| 280 // Ping the database to keep the connection fresh. | 280 // Ping the database to keep the connection fresh. |
| 281 go func() { | 281 go func() { |
| 282 c := time.Tick(1 * time.Minute) | 282 c := time.Tick(1 * time.Minute) |
| 283 for _ = range c { | 283 for _ = range c { |
| 284 if err := db.Ping(); err != nil { | 284 if err := db.Ping(); err != nil { |
| 285 » » » » log.Printf("ERROR: Database failed to respond: %
q\n", err) | 285 » » » » glog.Errorf("Database failed to respond: %q\n",
err) |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 }() | 288 }() |
| 289 | 289 |
| 290 metrics.RegisterRuntimeMemStats(metrics.DefaultRegistry) | 290 metrics.RegisterRuntimeMemStats(metrics.DefaultRegistry) |
| 291 go metrics.CaptureRuntimeMemStats(metrics.DefaultRegistry, 1*time.Minute
) | 291 go metrics.CaptureRuntimeMemStats(metrics.DefaultRegistry, 1*time.Minute
) |
| 292 | 292 |
| 293 // Start reporting metrics. | 293 // Start reporting metrics. |
| 294 // TODO(jcgregorio) We need a centrialized config server for storing thi
ngs | 294 // TODO(jcgregorio) We need a centrialized config server for storing thi
ngs |
| 295 // like the IP address of the Graphite monitor. | 295 // like the IP address of the Graphite monitor. |
| 296 addr, _ := net.ResolveTCPAddr("tcp", "skia-monitoring-b:2003") | 296 addr, _ := net.ResolveTCPAddr("tcp", "skia-monitoring-b:2003") |
| 297 go metrics.Graphite(metrics.DefaultRegistry, 1*time.Minute, "webtry", ad
dr) | 297 go metrics.Graphite(metrics.DefaultRegistry, 1*time.Minute, "webtry", ad
dr) |
| 298 | 298 |
| 299 writeOutAllSourceImages() | 299 writeOutAllSourceImages() |
| 300 } | 300 } |
| 301 | 301 |
| 302 func writeOutAllSourceImages() { | 302 func writeOutAllSourceImages() { |
| 303 // Pull all the source images from the db and write them out to inout. | 303 // Pull all the source images from the db and write them out to inout. |
| 304 rows, err := db.Query("SELECT id, image, create_ts FROM source_images OR
DER BY create_ts DESC") | 304 rows, err := db.Query("SELECT id, image, create_ts FROM source_images OR
DER BY create_ts DESC") |
| 305 | 305 |
| 306 if err != nil { | 306 if err != nil { |
| 307 » » log.Printf("ERROR: Failed to open connection to SQL server: %q\n
", err) | 307 » » glog.Errorf("Failed to open connection to SQL server: %q\n", err
) |
| 308 panic(err) | 308 panic(err) |
| 309 } | 309 } |
| 310 for rows.Next() { | 310 for rows.Next() { |
| 311 var id int | 311 var id int |
| 312 var image []byte | 312 var image []byte |
| 313 var create_ts time.Time | 313 var create_ts time.Time |
| 314 if err := rows.Scan(&id, &image, &create_ts); err != nil { | 314 if err := rows.Scan(&id, &image, &create_ts); err != nil { |
| 315 » » » log.Printf("Error: failed to fetch from database: %q", e
rr) | 315 » » » glog.Errorf("failed to fetch from database: %q", err) |
| 316 continue | 316 continue |
| 317 } | 317 } |
| 318 filename := fmt.Sprintf("../../../inout/image-%d.png", id) | 318 filename := fmt.Sprintf("../../../inout/image-%d.png", id) |
| 319 if _, err := os.Stat(filename); os.IsExist(err) { | 319 if _, err := os.Stat(filename); os.IsExist(err) { |
| 320 » » » log.Printf("Skipping write since file exists: %q", filen
ame) | 320 » » » glog.Infof("Skipping write since file exists: %q", filen
ame) |
| 321 continue | 321 continue |
| 322 } | 322 } |
| 323 if err := ioutil.WriteFile(filename, image, 0666); err != nil { | 323 if err := ioutil.WriteFile(filename, image, 0666); err != nil { |
| 324 » » » log.Printf("Error: failed to write image file: %q", err) | 324 » » » glog.Errorf("failed to write image file: %q", err) |
| 325 } | 325 } |
| 326 } | 326 } |
| 327 } | 327 } |
| 328 | 328 |
| 329 // Titlebar is used in titlebar template expansion. | 329 // Titlebar is used in titlebar template expansion. |
| 330 type Titlebar struct { | 330 type Titlebar struct { |
| 331 GitHash string | 331 GitHash string |
| 332 GitInfo string | 332 GitInfo string |
| 333 } | 333 } |
| 334 | 334 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 Message string `json:"message"` | 407 Message string `json:"message"` |
| 408 StdOut string `json:"stdout"` | 408 StdOut string `json:"stdout"` |
| 409 Img string `json:"img"` | 409 Img string `json:"img"` |
| 410 Hash string `json:"hash"` | 410 Hash string `json:"hash"` |
| 411 } | 411 } |
| 412 | 412 |
| 413 // doCmd executes the given command line string; the command being | 413 // doCmd executes the given command line string; the command being |
| 414 // run is expected to not care what its current working directory is. | 414 // run is expected to not care what its current working directory is. |
| 415 // Returns the stdout and stderr. | 415 // Returns the stdout and stderr. |
| 416 func doCmd(commandLine string) (string, error) { | 416 func doCmd(commandLine string) (string, error) { |
| 417 » log.Printf("Command: %q\n", commandLine) | 417 » glog.Infof("Command: %q\n", commandLine) |
| 418 programAndArgs := strings.SplitN(commandLine, " ", 2) | 418 programAndArgs := strings.SplitN(commandLine, " ", 2) |
| 419 program := programAndArgs[0] | 419 program := programAndArgs[0] |
| 420 args := []string{} | 420 args := []string{} |
| 421 if len(programAndArgs) > 1 { | 421 if len(programAndArgs) > 1 { |
| 422 args = strings.Split(programAndArgs[1], " ") | 422 args = strings.Split(programAndArgs[1], " ") |
| 423 } | 423 } |
| 424 cmd := exec.Command(program, args...) | 424 cmd := exec.Command(program, args...) |
| 425 message, err := cmd.CombinedOutput() | 425 message, err := cmd.CombinedOutput() |
| 426 » log.Printf("StdOut + StdErr: %s\n", string(message)) | 426 » glog.Infof("StdOut + StdErr: %s\n", string(message)) |
| 427 if err != nil { | 427 if err != nil { |
| 428 » » log.Printf("Exit status: %s\n", err.Error()) | 428 » » glog.Errorf("Exit status: %s\n", err) |
| 429 return string(message), fmt.Errorf("Failed to run command.") | 429 return string(message), fmt.Errorf("Failed to run command.") |
| 430 } | 430 } |
| 431 return string(message), nil | 431 return string(message), nil |
| 432 } | 432 } |
| 433 | 433 |
| 434 // reportError formats an HTTP error response and also logs the detailed error m
essage. | 434 // reportError formats an HTTP error response and also logs the detailed error m
essage. |
| 435 func reportError(w http.ResponseWriter, r *http.Request, err error, message stri
ng) { | 435 func reportError(w http.ResponseWriter, r *http.Request, err error, message stri
ng) { |
| 436 » log.Printf("Error: %s\n%s", message, err.Error()) | 436 » glog.Errorf("%s\n%s", message, err) |
| 437 w.Header().Set("Content-Type", "text/plain") | 437 w.Header().Set("Content-Type", "text/plain") |
| 438 http.Error(w, message, 500) | 438 http.Error(w, message, 500) |
| 439 } | 439 } |
| 440 | 440 |
| 441 // reportTryError formats an HTTP error response in JSON and also logs the detai
led error message. | 441 // reportTryError formats an HTTP error response in JSON and also logs the detai
led error message. |
| 442 func reportTryError(w http.ResponseWriter, r *http.Request, err error, message,
hash string) { | 442 func reportTryError(w http.ResponseWriter, r *http.Request, err error, message,
hash string) { |
| 443 m := response{ | 443 m := response{ |
| 444 Message: message, | 444 Message: message, |
| 445 Hash: hash, | 445 Hash: hash, |
| 446 } | 446 } |
| 447 » log.Printf("Error: %s\n%s", message, err.Error()) | 447 » glog.Errorf("%s\n%s", message, err) |
| 448 resp, err := json.Marshal(m) | 448 resp, err := json.Marshal(m) |
| 449 if err != nil { | 449 if err != nil { |
| 450 http.Error(w, "Failed to serialize a response", 500) | 450 http.Error(w, "Failed to serialize a response", 500) |
| 451 return | 451 return |
| 452 } | 452 } |
| 453 w.Header().Set("Content-Type", "text/plain") | 453 w.Header().Set("Content-Type", "text/plain") |
| 454 w.Write(resp) | 454 w.Write(resp) |
| 455 } | 455 } |
| 456 | 456 |
| 457 func writeToDatabase(hash string, code string, workspaceName string, source int,
width, height int, gpu bool) { | 457 func writeToDatabase(hash string, code string, workspaceName string, source int,
width, height int, gpu bool) { |
| 458 if db == nil { | 458 if db == nil { |
| 459 return | 459 return |
| 460 } | 460 } |
| 461 if _, err := db.Exec("INSERT INTO webtry (code, hash, width, height, gpu
, source_image_id) VALUES(?, ?, ?, ?, ?, ?)", code, hash, width, height, gpu, so
urce); err != nil { | 461 if _, err := db.Exec("INSERT INTO webtry (code, hash, width, height, gpu
, source_image_id) VALUES(?, ?, ?, ?, ?, ?)", code, hash, width, height, gpu, so
urce); err != nil { |
| 462 » » log.Printf("ERROR: Failed to insert code into database: %q\n", e
rr) | 462 » » glog.Errorf("Failed to insert code into database: %q\n", err) |
| 463 } | 463 } |
| 464 if workspaceName != "" { | 464 if workspaceName != "" { |
| 465 if _, err := db.Exec("INSERT INTO workspacetry (name, hash, widt
h, height, gpu, source_image_id) VALUES(?, ?, ?, ?, ?, ?)", workspaceName, hash,
width, height, gpu, source); err != nil { | 465 if _, err := db.Exec("INSERT INTO workspacetry (name, hash, widt
h, height, gpu, source_image_id) VALUES(?, ?, ?, ?, ?, ?)", workspaceName, hash,
width, height, gpu, source); err != nil { |
| 466 » » » log.Printf("ERROR: Failed to insert into workspacetry ta
ble: %q\n", err) | 466 » » » glog.Errorf("Failed to insert into workspacetry table: %
q\n", err) |
| 467 } | 467 } |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 | 470 |
| 471 type Sources struct { | 471 type Sources struct { |
| 472 Id int `json:"id"` | 472 Id int `json:"id"` |
| 473 } | 473 } |
| 474 | 474 |
| 475 // sourcesHandler serves up the PNG of a specific try. | 475 // sourcesHandler serves up the PNG of a specific try. |
| 476 func sourcesHandler(w http.ResponseWriter, r *http.Request) { | 476 func sourcesHandler(w http.ResponseWriter, r *http.Request) { |
| 477 » log.Printf("Sources Handler: %q\n", r.URL.Path) | 477 » glog.Infof("Sources Handler: %q\n", r.URL.Path) |
| 478 if r.Method == "GET" { | 478 if r.Method == "GET" { |
| 479 rows, err := db.Query("SELECT id, create_ts FROM source_images W
HERE hidden=0 ORDER BY create_ts DESC") | 479 rows, err := db.Query("SELECT id, create_ts FROM source_images W
HERE hidden=0 ORDER BY create_ts DESC") |
| 480 | 480 |
| 481 if err != nil { | 481 if err != nil { |
| 482 http.Error(w, fmt.Sprintf("Failed to query sources: %s."
, err), 500) | 482 http.Error(w, fmt.Sprintf("Failed to query sources: %s."
, err), 500) |
| 483 } | 483 } |
| 484 sources := make([]Sources, 0, 0) | 484 sources := make([]Sources, 0, 0) |
| 485 for rows.Next() { | 485 for rows.Next() { |
| 486 var id int | 486 var id int |
| 487 var create_ts time.Time | 487 var create_ts time.Time |
| 488 if err := rows.Scan(&id, &create_ts); err != nil { | 488 if err := rows.Scan(&id, &create_ts); err != nil { |
| 489 » » » » log.Printf("Error: failed to fetch from database
: %q", err) | 489 » » » » glog.Errorf("failed to fetch from database: %q",
err) |
| 490 continue | 490 continue |
| 491 } | 491 } |
| 492 sources = append(sources, Sources{Id: id}) | 492 sources = append(sources, Sources{Id: id}) |
| 493 } | 493 } |
| 494 | 494 |
| 495 resp, err := json.Marshal(sources) | 495 resp, err := json.Marshal(sources) |
| 496 if err != nil { | 496 if err != nil { |
| 497 reportError(w, r, err, "Failed to serialize a response."
) | 497 reportError(w, r, err, "Failed to serialize a response."
) |
| 498 return | 498 return |
| 499 } | 499 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 523 if err != nil { | 523 if err != nil { |
| 524 http.Error(w, fmt.Sprintf("Failed to decode image: %s.",
err), 500) | 524 http.Error(w, fmt.Sprintf("Failed to decode image: %s.",
err), 500) |
| 525 return | 525 return |
| 526 } | 526 } |
| 527 var b bytes.Buffer | 527 var b bytes.Buffer |
| 528 png.Encode(&b, m) | 528 png.Encode(&b, m) |
| 529 bounds := m.Bounds() | 529 bounds := m.Bounds() |
| 530 width := bounds.Max.Y - bounds.Min.Y | 530 width := bounds.Max.Y - bounds.Min.Y |
| 531 height := bounds.Max.X - bounds.Min.X | 531 height := bounds.Max.X - bounds.Min.X |
| 532 if _, err := db.Exec("INSERT INTO source_images (image, width, h
eight) VALUES(?, ?, ?)", b.Bytes(), width, height); err != nil { | 532 if _, err := db.Exec("INSERT INTO source_images (image, width, h
eight) VALUES(?, ?, ?)", b.Bytes(), width, height); err != nil { |
| 533 » » » log.Printf("ERROR: Failed to insert sources into databas
e: %q\n", err) | 533 » » » glog.Errorf("Failed to insert sources into database: %q\
n", err) |
| 534 http.Error(w, fmt.Sprintf("Failed to store image: %s.",
err), 500) | 534 http.Error(w, fmt.Sprintf("Failed to store image: %s.",
err), 500) |
| 535 return | 535 return |
| 536 } | 536 } |
| 537 go writeOutAllSourceImages() | 537 go writeOutAllSourceImages() |
| 538 | 538 |
| 539 // Now redirect back to where we came from. | 539 // Now redirect back to where we came from. |
| 540 http.Redirect(w, r, r.Referer(), 302) | 540 http.Redirect(w, r, r.Referer(), 302) |
| 541 } else { | 541 } else { |
| 542 http.NotFound(w, r) | 542 http.NotFound(w, r) |
| 543 return | 543 return |
| 544 } | 544 } |
| 545 } | 545 } |
| 546 | 546 |
| 547 // imageHandler serves up the PNG of a specific try. | 547 // imageHandler serves up the PNG of a specific try. |
| 548 func imageHandler(w http.ResponseWriter, r *http.Request) { | 548 func imageHandler(w http.ResponseWriter, r *http.Request) { |
| 549 » log.Printf("Image Handler: %q\n", r.URL.Path) | 549 » glog.Infof("Image Handler: %q\n", r.URL.Path) |
| 550 if r.Method != "GET" { | 550 if r.Method != "GET" { |
| 551 http.NotFound(w, r) | 551 http.NotFound(w, r) |
| 552 return | 552 return |
| 553 } | 553 } |
| 554 match := imageLink.FindStringSubmatch(r.URL.Path) | 554 match := imageLink.FindStringSubmatch(r.URL.Path) |
| 555 if len(match) != 2 { | 555 if len(match) != 2 { |
| 556 http.NotFound(w, r) | 556 http.NotFound(w, r) |
| 557 return | 557 return |
| 558 } | 558 } |
| 559 filename := match[1] | 559 filename := match[1] |
| 560 w.Header().Set("Content-Type", "image/png") | 560 w.Header().Set("Content-Type", "image/png") |
| 561 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) | 561 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) |
| 562 } | 562 } |
| 563 | 563 |
| 564 type Try struct { | 564 type Try struct { |
| 565 Hash string `json:"hash"` | 565 Hash string `json:"hash"` |
| 566 Source int | 566 Source int |
| 567 CreateTS string `json:"create_ts"` | 567 CreateTS string `json:"create_ts"` |
| 568 } | 568 } |
| 569 | 569 |
| 570 type Recent struct { | 570 type Recent struct { |
| 571 Tries []Try | 571 Tries []Try |
| 572 Titlebar Titlebar | 572 Titlebar Titlebar |
| 573 } | 573 } |
| 574 | 574 |
| 575 // recentHandler shows the last 20 tries. | 575 // recentHandler shows the last 20 tries. |
| 576 func recentHandler(w http.ResponseWriter, r *http.Request) { | 576 func recentHandler(w http.ResponseWriter, r *http.Request) { |
| 577 » log.Printf("Recent Handler: %q\n", r.URL.Path) | 577 » glog.Infof("Recent Handler: %q\n", r.URL.Path) |
| 578 | 578 |
| 579 var err error | 579 var err error |
| 580 rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY creat
e_ts DESC LIMIT 20") | 580 rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY creat
e_ts DESC LIMIT 20") |
| 581 if err != nil { | 581 if err != nil { |
| 582 http.NotFound(w, r) | 582 http.NotFound(w, r) |
| 583 return | 583 return |
| 584 } | 584 } |
| 585 recent := []Try{} | 585 recent := []Try{} |
| 586 for rows.Next() { | 586 for rows.Next() { |
| 587 var hash string | 587 var hash string |
| 588 var create_ts time.Time | 588 var create_ts time.Time |
| 589 if err := rows.Scan(&create_ts, &hash); err != nil { | 589 if err := rows.Scan(&create_ts, &hash); err != nil { |
| 590 » » » log.Printf("Error: failed to fetch from database: %q", e
rr) | 590 » » » glog.Errorf("failed to fetch from database: %q", err) |
| 591 continue | 591 continue |
| 592 } | 592 } |
| 593 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form
at("2006-02-01")}) | 593 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form
at("2006-02-01")}) |
| 594 } | 594 } |
| 595 w.Header().Set("Content-Type", "text/html") | 595 w.Header().Set("Content-Type", "text/html") |
| 596 if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titl
ebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { | 596 if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titl
ebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
| 597 » » log.Printf("ERROR: Failed to expand template: %q\n", err) | 597 » » glog.Errorf("Failed to expand template: %q\n", err) |
| 598 } | 598 } |
| 599 } | 599 } |
| 600 | 600 |
| 601 type Workspace struct { | 601 type Workspace struct { |
| 602 Name string | 602 Name string |
| 603 Code string | 603 Code string |
| 604 Hash string | 604 Hash string |
| 605 Width int | 605 Width int |
| 606 Height int | 606 Height int |
| 607 Source int | 607 Source int |
| 608 GPU bool | 608 GPU bool |
| 609 Tries []Try | 609 Tries []Try |
| 610 Titlebar Titlebar | 610 Titlebar Titlebar |
| 611 } | 611 } |
| 612 | 612 |
| 613 // newWorkspace generates a new random workspace name and stores it in the datab
ase. | 613 // newWorkspace generates a new random workspace name and stores it in the datab
ase. |
| 614 func newWorkspace() (string, error) { | 614 func newWorkspace() (string, error) { |
| 615 for i := 0; i < 10; i++ { | 615 for i := 0; i < 10; i++ { |
| 616 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))] | 616 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))] |
| 617 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))] | 617 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))] |
| 618 suffix := rand.Intn(1000) | 618 suffix := rand.Intn(1000) |
| 619 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix) | 619 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix) |
| 620 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n
ame); err == nil { | 620 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n
ame); err == nil { |
| 621 return name, nil | 621 return name, nil |
| 622 } else { | 622 } else { |
| 623 » » » log.Printf("ERROR: Failed to insert workspace into datab
ase: %q\n", err) | 623 » » » glog.Errorf("Failed to insert workspace into database: %
q\n", err) |
| 624 } | 624 } |
| 625 } | 625 } |
| 626 return "", fmt.Errorf("Failed to create a new workspace") | 626 return "", fmt.Errorf("Failed to create a new workspace") |
| 627 } | 627 } |
| 628 | 628 |
| 629 // getCode returns the code for a given hash, or the empty string if not found. | 629 // getCode returns the code for a given hash, or the empty string if not found. |
| 630 func getCode(hash string) (string, int, int, int, bool, error) { | 630 func getCode(hash string) (string, int, int, int, bool, error) { |
| 631 code := "" | 631 code := "" |
| 632 width := 0 | 632 width := 0 |
| 633 height := 0 | 633 height := 0 |
| 634 source := 0 | 634 source := 0 |
| 635 gpu := false | 635 gpu := false |
| 636 if err := db.QueryRow("SELECT code, width, height, gpu, source_image_id
FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &gpu, &source); er
r != nil { | 636 if err := db.QueryRow("SELECT code, width, height, gpu, source_image_id
FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &gpu, &source); er
r != nil { |
| 637 » » log.Printf("ERROR: Code for hash is missing: %q\n", err) | 637 » » glog.Errorf("Code for hash is missing: %q\n", err) |
| 638 return code, width, height, source, gpu, err | 638 return code, width, height, source, gpu, err |
| 639 } | 639 } |
| 640 return code, width, height, source, gpu, nil | 640 return code, width, height, source, gpu, nil |
| 641 } | 641 } |
| 642 | 642 |
| 643 func workspaceHandler(w http.ResponseWriter, r *http.Request) { | 643 func workspaceHandler(w http.ResponseWriter, r *http.Request) { |
| 644 » log.Printf("Workspace Handler: %q\n", r.URL.Path) | 644 » glog.Infof("Workspace Handler: %q\n", r.URL.Path) |
| 645 if r.Method == "GET" { | 645 if r.Method == "GET" { |
| 646 tries := []Try{} | 646 tries := []Try{} |
| 647 match := workspaceLink.FindStringSubmatch(r.URL.Path) | 647 match := workspaceLink.FindStringSubmatch(r.URL.Path) |
| 648 name := "" | 648 name := "" |
| 649 if len(match) == 2 { | 649 if len(match) == 2 { |
| 650 name = match[1] | 650 name = match[1] |
| 651 rows, err := db.Query("SELECT create_ts, hash, source_im
age_id FROM workspacetry WHERE name=? ORDER BY create_ts", name) | 651 rows, err := db.Query("SELECT create_ts, hash, source_im
age_id FROM workspacetry WHERE name=? ORDER BY create_ts", name) |
| 652 if err != nil { | 652 if err != nil { |
| 653 reportError(w, r, err, "Failed to select.") | 653 reportError(w, r, err, "Failed to select.") |
| 654 return | 654 return |
| 655 } | 655 } |
| 656 for rows.Next() { | 656 for rows.Next() { |
| 657 var hash string | 657 var hash string |
| 658 var create_ts time.Time | 658 var create_ts time.Time |
| 659 var source int | 659 var source int |
| 660 if err := rows.Scan(&create_ts, &hash, &source);
err != nil { | 660 if err := rows.Scan(&create_ts, &hash, &source);
err != nil { |
| 661 » » » » » log.Printf("Error: failed to fetch from
database: %q", err) | 661 » » » » » glog.Errorf("failed to fetch from databa
se: %q", err) |
| 662 continue | 662 continue |
| 663 } | 663 } |
| 664 tries = append(tries, Try{Hash: hash, Source: so
urce, CreateTS: create_ts.Format("2006-02-01")}) | 664 tries = append(tries, Try{Hash: hash, Source: so
urce, CreateTS: create_ts.Format("2006-02-01")}) |
| 665 } | 665 } |
| 666 } | 666 } |
| 667 var code string | 667 var code string |
| 668 var hash string | 668 var hash string |
| 669 var width int | 669 var width int |
| 670 var height int | 670 var height int |
| 671 source := 0 | 671 source := 0 |
| 672 gpu := false | 672 gpu := false |
| 673 if len(tries) == 0 { | 673 if len(tries) == 0 { |
| 674 code = DEFAULT_SAMPLE | 674 code = DEFAULT_SAMPLE |
| 675 width = 256 | 675 width = 256 |
| 676 height = 256 | 676 height = 256 |
| 677 } else { | 677 } else { |
| 678 hash = tries[len(tries)-1].Hash | 678 hash = tries[len(tries)-1].Hash |
| 679 code, width, height, source, gpu, _ = getCode(hash) | 679 code, width, height, source, gpu, _ = getCode(hash) |
| 680 } | 680 } |
| 681 w.Header().Set("Content-Type", "text/html") | 681 w.Header().Set("Content-Type", "text/html") |
| 682 if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C
ode: code, Name: name, Hash: hash, Width: width, Height: height, GPU: gpu, Sourc
e: source, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil
{ | 682 if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C
ode: code, Name: name, Hash: hash, Width: width, Height: height, GPU: gpu, Sourc
e: source, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil
{ |
| 683 » » » log.Printf("ERROR: Failed to expand template: %q\n", err
) | 683 » » » glog.Errorf("Failed to expand template: %q\n", err) |
| 684 } | 684 } |
| 685 } else if r.Method == "POST" { | 685 } else if r.Method == "POST" { |
| 686 name, err := newWorkspace() | 686 name, err := newWorkspace() |
| 687 if err != nil { | 687 if err != nil { |
| 688 http.Error(w, "Failed to create a new workspace.", 500) | 688 http.Error(w, "Failed to create a new workspace.", 500) |
| 689 return | 689 return |
| 690 } | 690 } |
| 691 http.Redirect(w, r, "/w/"+name, 302) | 691 http.Redirect(w, r, "/w/"+name, 302) |
| 692 } | 692 } |
| 693 } | 693 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 707 Code string `json:"code"` | 707 Code string `json:"code"` |
| 708 Width int `json:"width"` | 708 Width int `json:"width"` |
| 709 Height int `json:"height"` | 709 Height int `json:"height"` |
| 710 GPU bool `json:"gpu"` | 710 GPU bool `json:"gpu"` |
| 711 Name string `json:"name"` // Optional name of the workspace the code
is in. | 711 Name string `json:"name"` // Optional name of the workspace the code
is in. |
| 712 Source int `json:"source"` // ID of the source image, 0 if none. | 712 Source int `json:"source"` // ID of the source image, 0 if none. |
| 713 } | 713 } |
| 714 | 714 |
| 715 // iframeHandler handles the GET and POST of the main page. | 715 // iframeHandler handles the GET and POST of the main page. |
| 716 func iframeHandler(w http.ResponseWriter, r *http.Request) { | 716 func iframeHandler(w http.ResponseWriter, r *http.Request) { |
| 717 » log.Printf("IFrame Handler: %q\n", r.URL.Path) | 717 » glog.Infof("IFrame Handler: %q\n", r.URL.Path) |
| 718 if r.Method != "GET" { | 718 if r.Method != "GET" { |
| 719 http.NotFound(w, r) | 719 http.NotFound(w, r) |
| 720 return | 720 return |
| 721 } | 721 } |
| 722 match := iframeLink.FindStringSubmatch(r.URL.Path) | 722 match := iframeLink.FindStringSubmatch(r.URL.Path) |
| 723 if len(match) != 2 { | 723 if len(match) != 2 { |
| 724 http.NotFound(w, r) | 724 http.NotFound(w, r) |
| 725 return | 725 return |
| 726 } | 726 } |
| 727 hash := match[1] | 727 hash := match[1] |
| 728 if db == nil { | 728 if db == nil { |
| 729 http.NotFound(w, r) | 729 http.NotFound(w, r) |
| 730 return | 730 return |
| 731 } | 731 } |
| 732 var code string | 732 var code string |
| 733 code, width, height, source, gpu, err := getCode(hash) | 733 code, width, height, source, gpu, err := getCode(hash) |
| 734 if err != nil { | 734 if err != nil { |
| 735 http.NotFound(w, r) | 735 http.NotFound(w, r) |
| 736 return | 736 return |
| 737 } | 737 } |
| 738 // Expand the template. | 738 // Expand the template. |
| 739 w.Header().Set("Content-Type", "text/html") | 739 w.Header().Set("Content-Type", "text/html") |
| 740 if err := iframeTemplate.Execute(w, userCode{Code: code, Width: width, H
eight: height, GPU: gpu, Hash: hash, Source: source}); err != nil { | 740 if err := iframeTemplate.Execute(w, userCode{Code: code, Width: width, H
eight: height, GPU: gpu, Hash: hash, Source: source}); err != nil { |
| 741 » » log.Printf("ERROR: Failed to expand template: %q\n", err) | 741 » » glog.Errorf("Failed to expand template: %q\n", err) |
| 742 } | 742 } |
| 743 } | 743 } |
| 744 | 744 |
| 745 type TryInfo struct { | 745 type TryInfo struct { |
| 746 Hash string `json:"hash"` | 746 Hash string `json:"hash"` |
| 747 Code string `json:"code"` | 747 Code string `json:"code"` |
| 748 Width int `json:"width"` | 748 Width int `json:"width"` |
| 749 Height int `json:"height"` | 749 Height int `json:"height"` |
| 750 GPU bool `json:"gpu"` | 750 GPU bool `json:"gpu"` |
| 751 Source int `json:"source"` | 751 Source int `json:"source"` |
| 752 } | 752 } |
| 753 | 753 |
| 754 // tryInfoHandler returns information about a specific try. | 754 // tryInfoHandler returns information about a specific try. |
| 755 func tryInfoHandler(w http.ResponseWriter, r *http.Request) { | 755 func tryInfoHandler(w http.ResponseWriter, r *http.Request) { |
| 756 » log.Printf("Try Info Handler: %q\n", r.URL.Path) | 756 » glog.Infof("Try Info Handler: %q\n", r.URL.Path) |
| 757 if r.Method != "GET" { | 757 if r.Method != "GET" { |
| 758 http.NotFound(w, r) | 758 http.NotFound(w, r) |
| 759 return | 759 return |
| 760 } | 760 } |
| 761 match := tryInfoLink.FindStringSubmatch(r.URL.Path) | 761 match := tryInfoLink.FindStringSubmatch(r.URL.Path) |
| 762 if len(match) != 2 { | 762 if len(match) != 2 { |
| 763 http.NotFound(w, r) | 763 http.NotFound(w, r) |
| 764 return | 764 return |
| 765 } | 765 } |
| 766 hash := match[1] | 766 hash := match[1] |
| (...skipping 14 matching lines...) Expand all Loading... |
| 781 if err != nil { | 781 if err != nil { |
| 782 reportError(w, r, err, "Failed to serialize a response.") | 782 reportError(w, r, err, "Failed to serialize a response.") |
| 783 return | 783 return |
| 784 } | 784 } |
| 785 w.Header().Set("Content-Type", "application/json") | 785 w.Header().Set("Content-Type", "application/json") |
| 786 w.Write(resp) | 786 w.Write(resp) |
| 787 } | 787 } |
| 788 | 788 |
| 789 func cleanCompileOutput(s, hash string) string { | 789 func cleanCompileOutput(s, hash string) string { |
| 790 old := "../../../cache/src/" + hash + ".cpp:" | 790 old := "../../../cache/src/" + hash + ".cpp:" |
| 791 » log.Printf("INFO: replacing %q\n", old) | 791 » glog.Infof("replacing %q\n", old) |
| 792 return strings.Replace(s, old, "usercode.cpp:", -1) | 792 return strings.Replace(s, old, "usercode.cpp:", -1) |
| 793 } | 793 } |
| 794 | 794 |
| 795 // mainHandler handles the GET and POST of the main page. | 795 // mainHandler handles the GET and POST of the main page. |
| 796 func mainHandler(w http.ResponseWriter, r *http.Request) { | 796 func mainHandler(w http.ResponseWriter, r *http.Request) { |
| 797 » log.Printf("Main Handler: %q\n", r.URL.Path) | 797 » glog.Infof("Main Handler: %q\n", r.URL.Path) |
| 798 requestsCounter.Inc(1) | 798 requestsCounter.Inc(1) |
| 799 if r.Method == "GET" { | 799 if r.Method == "GET" { |
| 800 code := DEFAULT_SAMPLE | 800 code := DEFAULT_SAMPLE |
| 801 source := 0 | 801 source := 0 |
| 802 width := 256 | 802 width := 256 |
| 803 height := 256 | 803 height := 256 |
| 804 gpu := false | 804 gpu := false |
| 805 match := directLink.FindStringSubmatch(r.URL.Path) | 805 match := directLink.FindStringSubmatch(r.URL.Path) |
| 806 var hash string | 806 var hash string |
| 807 if len(match) == 2 && r.URL.Path != "/" { | 807 if len(match) == 2 && r.URL.Path != "/" { |
| 808 hash = match[1] | 808 hash = match[1] |
| 809 if db == nil { | 809 if db == nil { |
| 810 http.NotFound(w, r) | 810 http.NotFound(w, r) |
| 811 return | 811 return |
| 812 } | 812 } |
| 813 // Update 'code' with the code found in the database. | 813 // Update 'code' with the code found in the database. |
| 814 if err := db.QueryRow("SELECT code, width, height, gpu,
source_image_id FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &g
pu, &source); err != nil { | 814 if err := db.QueryRow("SELECT code, width, height, gpu,
source_image_id FROM webtry WHERE hash=?", hash).Scan(&code, &width, &height, &g
pu, &source); err != nil { |
| 815 http.NotFound(w, r) | 815 http.NotFound(w, r) |
| 816 return | 816 return |
| 817 } | 817 } |
| 818 } | 818 } |
| 819 // Expand the template. | 819 // Expand the template. |
| 820 w.Header().Set("Content-Type", "text/html") | 820 w.Header().Set("Content-Type", "text/html") |
| 821 if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha
sh, Source: source, Width: width, Height: height, GPU: gpu, Titlebar: Titlebar{G
itHash: gitHash, GitInfo: gitInfo}}); err != nil { | 821 if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha
sh, Source: source, Width: width, Height: height, GPU: gpu, Titlebar: Titlebar{G
itHash: gitHash, GitInfo: gitInfo}}); err != nil { |
| 822 » » » log.Printf("ERROR: Failed to expand template: %q\n", err
) | 822 » » » glog.Errorf("Failed to expand template: %q\n", err) |
| 823 } | 823 } |
| 824 } else if r.Method == "POST" { | 824 } else if r.Method == "POST" { |
| 825 w.Header().Set("Content-Type", "application/json") | 825 w.Header().Set("Content-Type", "application/json") |
| 826 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) | 826 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) |
| 827 n, err := buf.ReadFrom(r.Body) | 827 n, err := buf.ReadFrom(r.Body) |
| 828 if err != nil { | 828 if err != nil { |
| 829 reportTryError(w, r, err, "Failed to read a request body
.", "") | 829 reportTryError(w, r, err, "Failed to read a request body
.", "") |
| 830 return | 830 return |
| 831 } | 831 } |
| 832 if n == MAX_TRY_SIZE { | 832 if n == MAX_TRY_SIZE { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler)) | 900 http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler)) |
| 901 http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler)) | 901 http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler)) |
| 902 http.HandleFunc("/sources/", autogzip.HandleFunc(sourcesHandler)) | 902 http.HandleFunc("/sources/", autogzip.HandleFunc(sourcesHandler)) |
| 903 | 903 |
| 904 // Resources are served directly | 904 // Resources are served directly |
| 905 // TODO add support for caching/etags/gzip | 905 // TODO add support for caching/etags/gzip |
| 906 http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./")))) | 906 http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./")))) |
| 907 | 907 |
| 908 // TODO Break out /c/ as it's own handler. | 908 // TODO Break out /c/ as it's own handler. |
| 909 http.HandleFunc("/", autogzip.HandleFunc(mainHandler)) | 909 http.HandleFunc("/", autogzip.HandleFunc(mainHandler)) |
| 910 » log.Fatal(http.ListenAndServe(*port, nil)) | 910 » glog.Fatal(http.ListenAndServe(*port, nil)) |
| 911 } | 911 } |
| OLD | NEW |