diff --git a/api/auth.go b/api/auth.go index 011d512..d31d833 100644 --- a/api/auth.go +++ b/api/auth.go @@ -72,7 +72,9 @@ func (app *App) SignupUser(w http.ResponseWriter, r *http.Request) { if err != nil { app.Logger.Printf("Error decoding JSON: %v", err) w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid JSON format"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid JSON format"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -84,24 +86,30 @@ func (app *App) SignupUser(w http.ResponseWriter, r *http.Request) { if !matches || !domainMatches || u.Password == "" || u.Email == "" { app.Logger.Println("Validation failed: Invalid email or password") w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } // Check if the user already exists var existingUserID int query := `SELECT id FROM users WHERE email = ?` - err = app.DB.QueryRow(query, u.Email).Scan(&existingUserID) // Use `=` instead of `:=` + err = app.DB.QueryRow(query, u.Email).Scan(&existingUserID) if err != nil && err != sql.ErrNoRows { app.Logger.Printf("Database error: %v", err) w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Database error"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Database error"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } if existingUserID != 0 { w.WriteHeader(http.StatusConflict) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Email already in use"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Email already in use"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -110,7 +118,9 @@ func (app *App) SignupUser(w http.ResponseWriter, r *http.Request) { if err != nil { app.Logger.Printf("Error hashing password: %v", err) w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Error hashing password"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Error hashing password"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -120,12 +130,16 @@ func (app *App) SignupUser(w http.ResponseWriter, r *http.Request) { if err != nil { app.Logger.Printf("Failed to insert user: %v", err) w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(ErrorResponse{Message: fmt.Sprintf("Failed to insert user: %v", err)}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: fmt.Sprintf("Failed to insert user: %v", err)}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } w.WriteHeader(http.StatusCreated) - json.NewEncoder(w).Encode(map[string]string{"message": "User registered successfully"}) + if encodeErr := json.NewEncoder(w).Encode(map[string]string{"message": "User registered successfully"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } } func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { @@ -136,7 +150,9 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { if err != nil { app.Logger.Printf("Error decoding JSON: %v", err) w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid JSON format"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid JSON format"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -148,7 +164,9 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { if !matches || !domainMatches || u.Password == "" || u.Email == "" { app.Logger.Println("Validation failed: Invalid email or password") w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -159,14 +177,18 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { err = app.DB.QueryRow(query, u.Email).Scan(&existingUserID, &hashedPassword) if err == sql.ErrNoRows { w.WriteHeader(http.StatusNotFound) - json.NewEncoder(w).Encode(ErrorResponse{Message: "User doesn't exist!"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "User doesn't exist!"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } if err != nil { app.Logger.Printf("Database error: %v", err) w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Database error"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Database error"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -174,7 +196,9 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(u.Password)) if err == bcrypt.ErrMismatchedHashAndPassword { w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid email or password"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -183,7 +207,9 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { if err != nil { app.Logger.Printf("Error generating session token: %v", err) w.WriteHeader(http.StatusInternalServerError) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Error generating session token"}) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Error generating session token"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } return } @@ -197,54 +223,63 @@ func (app *App) LoginUser(w http.ResponseWriter, r *http.Request) { // Respond to the client with the session token w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(map[string]interface{}{ + if encodeErr := json.NewEncoder(w).Encode(map[string]interface{}{ "token": token, "existingUserID": existingUserID, "message": "User logged in successfully", - }) + }); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } } -func (app *App) VerifySessionToken(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Println("works") - // Get the session token from the cookie - cookie, err := r.Cookie("token") - fmt.Println("Cookie name", cookie) - if err != nil { - if err == http.ErrNoCookie { - // If the cookie is not set, return an unauthorized status - w.WriteHeader(http.StatusUnauthorized) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Unauthorized access"}) - return - } - // For any other type of error, return a bad request status - w.WriteHeader(http.StatusBadRequest) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Bad request"}) - return - } - - // Retrieve the session token from the cookie - sessionToken := cookie.Value - // Get the session from the store - session, exists := sessionStore.Get(sessionToken) - if !exists { - // If the session token is not valid, return unauthorized - w.WriteHeader(http.StatusUnauthorized) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid session token"}) - return - } - - // Check if the session has expired - if session.ExpiresAt.Before(time.Now()) { - // If the session is expired, return unauthorized - w.WriteHeader(http.StatusUnauthorized) - json.NewEncoder(w).Encode(ErrorResponse{Message: "Session expired"}) - return - } - - next.ServeHTTP(w, r) - }) +func (app *App) VerifySessionToken(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Get the session token from the cookie + cookie, err := r.Cookie("token") + if err != nil { + if err == http.ErrNoCookie { + // If the cookie is not set, return an unauthorized status + w.WriteHeader(http.StatusUnauthorized) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Unauthorized access"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } + return + } + // For any other type of error, return a bad request status + w.WriteHeader(http.StatusBadRequest) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Bad request"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } + return + } + + // Retrieve the session token from the cookie + sessionToken := cookie.Value + + // Get the session from the store + session, exists := sessionStore.Get(sessionToken) + if !exists { + // If the session token is not valid, return unauthorized + w.WriteHeader(http.StatusUnauthorized) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Invalid session token"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } + return + } + + // Check if the session has expired + if session.ExpiresAt.Before(time.Now()) { + // If the session is expired, return unauthorized + w.WriteHeader(http.StatusUnauthorized) + if encodeErr := json.NewEncoder(w).Encode(ErrorResponse{Message: "Session expired"}); encodeErr != nil { + app.Logger.Printf("Error encoding JSON: %v", encodeErr) + } + return + } + + next.ServeHTTP(w, r) + }) } func generateSessionToken() (string, error) { diff --git a/api/coverage.out b/api/coverage.out index e32e814..b8d2d09 100644 --- a/api/coverage.out +++ b/api/coverage.out @@ -2,44 +2,78 @@ mode: set mymodule/auth.go:39.59,43.2 3 0 mymodule/auth.go:46.58,51.2 4 0 mymodule/auth.go:67.68,72.16 3 0 -mymodule/auth.go:72.16,77.3 4 0 -mymodule/auth.go:79.2,84.69 4 0 -mymodule/auth.go:84.69,89.3 4 0 -mymodule/auth.go:92.2,95.40 4 0 -mymodule/auth.go:95.40,100.3 4 0 -mymodule/auth.go:102.2,102.25 1 0 -mymodule/auth.go:102.25,106.3 3 0 -mymodule/auth.go:109.2,110.16 2 0 -mymodule/auth.go:110.16,115.3 4 0 -mymodule/auth.go:118.2,120.16 3 0 -mymodule/auth.go:120.16,125.3 4 0 -mymodule/auth.go:127.2,128.89 2 0 -mymodule/auth.go:131.67,136.16 3 0 -mymodule/auth.go:136.16,141.3 4 0 -mymodule/auth.go:143.2,148.69 4 0 -mymodule/auth.go:148.69,153.3 4 0 -mymodule/auth.go:156.2,160.26 5 0 -mymodule/auth.go:160.26,164.3 3 0 -mymodule/auth.go:166.2,166.16 1 0 -mymodule/auth.go:166.16,171.3 4 0 -mymodule/auth.go:174.2,175.48 2 0 -mymodule/auth.go:175.48,179.3 3 0 -mymodule/auth.go:182.2,183.16 2 0 -mymodule/auth.go:183.16,188.3 4 0 -mymodule/auth.go:190.2,204.4 4 0 -mymodule/auth.go:207.68,208.71 1 0 -mymodule/auth.go:208.71,213.17 4 0 -mymodule/auth.go:213.17,214.31 1 0 -mymodule/auth.go:214.31,219.5 3 0 -mymodule/auth.go:221.4,223.10 3 0 -mymodule/auth.go:227.3,231.14 3 0 -mymodule/auth.go:231.14,236.4 3 0 -mymodule/auth.go:239.3,239.43 1 0 -mymodule/auth.go:239.43,244.4 3 0 -mymodule/auth.go:246.3,246.23 1 0 -mymodule/auth.go:250.45,253.16 3 0 -mymodule/auth.go:253.16,255.3 1 0 -mymodule/auth.go:256.2,256.50 1 0 +mymodule/auth.go:72.16,75.110 3 0 +mymodule/auth.go:75.110,77.4 1 0 +mymodule/auth.go:78.3,78.9 1 0 +mymodule/auth.go:81.2,86.69 4 0 +mymodule/auth.go:86.69,89.116 3 0 +mymodule/auth.go:89.116,91.4 1 0 +mymodule/auth.go:92.3,92.9 1 0 +mymodule/auth.go:96.2,99.40 4 0 +mymodule/auth.go:99.40,102.105 3 0 +mymodule/auth.go:102.105,104.4 1 0 +mymodule/auth.go:105.3,105.9 1 0 +mymodule/auth.go:108.2,108.25 1 0 +mymodule/auth.go:108.25,110.111 2 0 +mymodule/auth.go:110.111,112.4 1 0 +mymodule/auth.go:113.3,113.9 1 0 +mymodule/auth.go:117.2,118.16 2 0 +mymodule/auth.go:118.16,121.113 3 0 +mymodule/auth.go:121.113,123.4 1 0 +mymodule/auth.go:124.3,124.9 1 0 +mymodule/auth.go:128.2,130.16 3 0 +mymodule/auth.go:130.16,133.134 3 0 +mymodule/auth.go:133.134,135.4 1 0 +mymodule/auth.go:136.3,136.9 1 0 +mymodule/auth.go:139.2,140.124 2 0 +mymodule/auth.go:140.124,142.3 1 0 +mymodule/auth.go:145.67,150.16 3 0 +mymodule/auth.go:150.16,153.110 3 0 +mymodule/auth.go:153.110,155.4 1 0 +mymodule/auth.go:156.3,156.9 1 0 +mymodule/auth.go:159.2,164.69 4 0 +mymodule/auth.go:164.69,167.116 3 0 +mymodule/auth.go:167.116,169.4 1 0 +mymodule/auth.go:170.3,170.9 1 0 +mymodule/auth.go:174.2,178.26 5 0 +mymodule/auth.go:178.26,180.110 2 0 +mymodule/auth.go:180.110,182.4 1 0 +mymodule/auth.go:183.3,183.9 1 0 +mymodule/auth.go:186.2,186.16 1 0 +mymodule/auth.go:186.16,189.105 3 0 +mymodule/auth.go:189.105,191.4 1 0 +mymodule/auth.go:192.3,192.9 1 0 +mymodule/auth.go:196.2,197.48 2 0 +mymodule/auth.go:197.48,199.116 2 0 +mymodule/auth.go:199.116,201.4 1 0 +mymodule/auth.go:202.3,202.9 1 0 +mymodule/auth.go:206.2,207.16 2 0 +mymodule/auth.go:207.16,210.121 3 0 +mymodule/auth.go:210.121,212.4 1 0 +mymodule/auth.go:213.3,213.9 1 0 +mymodule/auth.go:216.2,230.23 4 0 +mymodule/auth.go:230.23,232.3 1 0 +mymodule/auth.go:236.68,237.74 1 0 +mymodule/auth.go:237.74,240.23 2 0 +mymodule/auth.go:240.23,241.40 1 0 +mymodule/auth.go:241.40,244.124 2 0 +mymodule/auth.go:244.124,246.18 1 0 +mymodule/auth.go:247.17,247.23 1 0 +mymodule/auth.go:250.13,251.112 2 0 +mymodule/auth.go:251.112,253.14 1 0 +mymodule/auth.go:254.13,254.19 1 0 +mymodule/auth.go:258.9,262.20 3 0 +mymodule/auth.go:262.20,265.122 2 0 +mymodule/auth.go:265.122,267.14 1 0 +mymodule/auth.go:268.13,268.19 1 0 +mymodule/auth.go:272.9,272.49 1 0 +mymodule/auth.go:272.49,275.116 2 0 +mymodule/auth.go:275.116,277.14 1 0 +mymodule/auth.go:278.13,278.19 1 0 +mymodule/auth.go:281.9,281.29 1 0 +mymodule/auth.go:285.45,288.16 3 0 +mymodule/auth.go:288.16,290.3 1 0 +mymodule/auth.go:291.2,291.50 1 0 mymodule/main.go:75.43,116.2 28 1 mymodule/main.go:118.13,124.16 4 0 mymodule/main.go:124.16,126.3 1 0 @@ -59,284 +93,287 @@ mymodule/main.go:191.62,194.2 2 1 mymodule/main.go:197.62,200.2 2 1 mymodule/main.go:203.91,206.2 2 1 mymodule/main.go:208.78,212.62 2 1 -mymodule/main.go:212.62,221.6 5 1 -mymodule/main.go:223.5,223.26 1 1 -mymodule/main.go:227.100,232.2 2 1 -mymodule/main.go:235.71,241.19 4 1 -mymodule/main.go:241.19,244.6 1 1 -mymodule/main.go:245.5,245.19 1 1 -mymodule/main.go:249.52,254.21 3 1 -mymodule/main.go:254.21,256.105 2 1 -mymodule/main.go:256.105,258.10 1 1 -mymodule/main.go:259.9,259.42 1 1 -mymodule/main.go:262.5,262.38 1 1 -mymodule/main.go:262.38,264.6 1 1 -mymodule/main.go:266.5,266.24 1 1 -mymodule/main.go:270.46,271.56 1 1 -mymodule/main.go:271.56,273.6 1 1 -mymodule/main.go:274.5,274.15 1 1 -mymodule/main.go:278.40,280.47 1 1 -mymodule/main.go:280.47,282.6 1 1 -mymodule/main.go:283.5,283.15 1 1 -mymodule/main.go:287.71,293.20 3 1 -mymodule/main.go:293.20,297.6 2 1 -mymodule/main.go:300.5,309.19 3 1 -mymodule/main.go:309.19,313.6 2 1 -mymodule/main.go:314.5,318.19 3 1 -mymodule/main.go:318.19,322.6 2 1 -mymodule/main.go:325.5,325.47 1 1 -mymodule/main.go:329.58,334.21 3 1 -mymodule/main.go:334.21,336.187 2 1 -mymodule/main.go:336.187,338.10 1 1 -mymodule/main.go:339.9,339.36 1 1 -mymodule/main.go:342.5,342.38 1 1 -mymodule/main.go:342.38,344.6 1 1 -mymodule/main.go:346.5,346.22 1 1 -mymodule/main.go:350.69,354.20 3 1 -mymodule/main.go:354.20,357.6 2 1 -mymodule/main.go:359.5,376.19 3 1 -mymodule/main.go:376.19,379.6 2 1 -mymodule/main.go:380.5,383.19 3 1 -mymodule/main.go:383.19,386.6 2 1 -mymodule/main.go:388.5,388.45 1 1 -mymodule/main.go:393.68,402.19 4 1 -mymodule/main.go:402.19,405.6 2 1 -mymodule/main.go:406.5,409.19 3 1 -mymodule/main.go:409.19,412.6 2 1 -mymodule/main.go:414.5,414.47 1 1 -mymodule/main.go:418.69,437.19 4 1 -mymodule/main.go:437.19,440.6 2 1 -mymodule/main.go:442.5,443.19 2 1 -mymodule/main.go:443.19,446.6 2 1 -mymodule/main.go:448.5,448.45 1 1 -mymodule/main.go:452.76,463.19 4 1 -mymodule/main.go:463.19,467.6 3 1 -mymodule/main.go:468.5,471.19 3 1 -mymodule/main.go:471.19,475.6 3 1 -mymodule/main.go:477.5,477.55 1 1 -mymodule/main.go:481.76,485.19 3 1 -mymodule/main.go:485.19,488.6 2 1 -mymodule/main.go:490.5,499.19 3 1 -mymodule/main.go:499.19,502.6 2 1 -mymodule/main.go:503.5,506.19 3 1 -mymodule/main.go:506.19,509.6 2 1 -mymodule/main.go:511.5,511.54 1 1 -mymodule/main.go:515.63,518.21 2 1 -mymodule/main.go:518.21,520.144 2 1 -mymodule/main.go:520.144,522.10 1 0 -mymodule/main.go:523.9,523.62 1 1 -mymodule/main.go:526.5,526.38 1 1 -mymodule/main.go:526.38,528.6 1 1 -mymodule/main.go:530.5,530.32 1 1 -mymodule/main.go:534.69,538.19 3 1 -mymodule/main.go:538.19,541.6 2 1 -mymodule/main.go:543.5,559.19 3 1 -mymodule/main.go:559.19,562.6 2 1 -mymodule/main.go:563.5,566.20 3 1 -mymodule/main.go:566.20,567.187 1 1 -mymodule/main.go:567.187,570.10 2 1 -mymodule/main.go:571.11,574.6 2 1 -mymodule/main.go:576.5,576.44 1 1 -mymodule/main.go:581.80,583.16 2 1 -mymodule/main.go:583.16,586.3 2 1 -mymodule/main.go:588.2,596.16 3 1 -mymodule/main.go:596.16,599.3 2 1 -mymodule/main.go:600.2,603.53 3 1 -mymodule/main.go:603.53,606.3 2 1 -mymodule/main.go:608.2,608.27 1 1 -mymodule/main.go:608.27,611.3 2 1 -mymodule/main.go:613.2,613.48 1 1 -mymodule/main.go:616.64,617.21 1 1 -mymodule/main.go:617.21,619.105 2 1 -mymodule/main.go:619.105,621.10 1 1 -mymodule/main.go:622.9,622.56 1 1 -mymodule/main.go:624.5,624.22 1 1 -mymodule/main.go:628.75,632.16 3 1 -mymodule/main.go:632.16,635.3 2 1 -mymodule/main.go:636.2,639.53 3 1 -mymodule/main.go:639.53,642.3 2 1 -mymodule/main.go:644.2,644.48 1 1 -mymodule/main.go:652.72,655.36 2 1 -mymodule/main.go:655.36,658.6 2 1 -mymodule/main.go:660.5,661.19 2 1 -mymodule/main.go:661.19,664.6 2 1 -mymodule/main.go:666.5,667.19 2 1 -mymodule/main.go:667.19,670.6 2 1 -mymodule/main.go:671.5,679.52 6 1 -mymodule/main.go:679.52,682.6 2 1 -mymodule/main.go:684.5,685.19 2 1 -mymodule/main.go:685.19,688.6 2 1 -mymodule/main.go:689.5,691.48 2 1 -mymodule/main.go:691.48,694.6 2 1 -mymodule/main.go:696.5,697.70 2 1 -mymodule/main.go:697.70,700.6 2 1 -mymodule/main.go:702.5,703.66 2 1 -mymodule/main.go:709.67,712.36 2 1 -mymodule/main.go:712.36,715.6 2 1 -mymodule/main.go:717.5,718.67 2 1 -mymodule/main.go:718.67,721.6 2 1 -mymodule/main.go:722.5,724.54 2 1 -mymodule/main.go:724.54,727.6 2 1 -mymodule/main.go:729.5,731.19 3 1 -mymodule/main.go:731.19,734.6 2 1 -mymodule/main.go:736.5,737.30 2 1 -mymodule/main.go:737.30,740.6 2 1 -mymodule/main.go:742.5,746.59 4 1 -mymodule/main.go:746.59,749.6 2 1 -mymodule/main.go:756.70,759.36 2 1 -mymodule/main.go:759.36,762.6 2 1 -mymodule/main.go:764.5,765.19 2 1 -mymodule/main.go:765.19,768.6 2 1 -mymodule/main.go:770.5,771.19 2 1 -mymodule/main.go:771.19,774.6 2 1 -mymodule/main.go:775.5,780.54 4 1 -mymodule/main.go:780.54,783.6 2 1 -mymodule/main.go:785.5,786.19 2 1 -mymodule/main.go:786.19,789.6 2 1 -mymodule/main.go:790.5,792.48 2 1 -mymodule/main.go:792.48,795.6 2 1 -mymodule/main.go:797.5,798.68 2 1 -mymodule/main.go:798.68,801.6 2 1 -mymodule/main.go:803.5,804.66 2 1 -mymodule/main.go:808.65,811.36 2 1 -mymodule/main.go:811.36,814.6 2 1 -mymodule/main.go:816.5,817.65 2 1 -mymodule/main.go:817.65,820.6 2 1 -mymodule/main.go:821.5,823.50 2 1 -mymodule/main.go:823.50,826.6 2 1 -mymodule/main.go:828.5,830.19 3 1 -mymodule/main.go:830.19,833.6 2 1 -mymodule/main.go:835.5,836.30 2 1 -mymodule/main.go:836.30,839.6 2 1 -mymodule/main.go:841.5,844.63 4 1 -mymodule/main.go:844.63,847.6 2 1 -mymodule/main.go:850.71,851.33 1 1 -mymodule/main.go:851.33,854.3 2 1 -mymodule/main.go:856.2,857.68 2 1 -mymodule/main.go:857.68,860.3 2 1 -mymodule/main.go:861.2,863.87 2 1 -mymodule/main.go:863.87,866.3 2 1 -mymodule/main.go:868.2,870.16 3 1 -mymodule/main.go:870.16,874.3 3 1 -mymodule/main.go:876.2,877.27 2 1 -mymodule/main.go:877.27,881.3 3 1 -mymodule/main.go:883.2,885.58 3 1 -mymodule/main.go:890.68,891.33 1 1 -mymodule/main.go:891.33,894.3 2 1 -mymodule/main.go:896.2,901.16 3 1 -mymodule/main.go:901.16,904.3 2 1 -mymodule/main.go:906.2,906.62 1 1 -mymodule/main.go:906.62,909.3 2 1 -mymodule/main.go:911.2,913.16 3 1 -mymodule/main.go:913.16,917.3 3 1 -mymodule/main.go:918.2,918.16 1 1 -mymodule/main.go:918.16,921.3 2 1 -mymodule/main.go:923.2,924.16 2 1 -mymodule/main.go:924.16,928.3 3 1 -mymodule/main.go:930.2,931.16 2 1 -mymodule/main.go:931.16,935.3 3 1 -mymodule/main.go:937.2,939.61 3 1 -mymodule/main.go:943.76,944.33 1 1 -mymodule/main.go:944.33,947.3 2 1 -mymodule/main.go:949.2,954.16 3 1 -mymodule/main.go:954.16,957.3 2 1 -mymodule/main.go:959.2,959.62 1 1 -mymodule/main.go:959.62,962.3 2 1 -mymodule/main.go:964.2,966.16 3 1 -mymodule/main.go:966.16,967.27 1 1 -mymodule/main.go:967.27,969.4 1 1 -mymodule/main.go:969.9,972.4 2 1 -mymodule/main.go:973.3,973.9 1 1 -mymodule/main.go:976.2,976.17 1 1 -mymodule/main.go:976.17,979.3 2 1 -mymodule/main.go:981.2,982.16 2 1 -mymodule/main.go:982.16,986.3 3 1 +mymodule/main.go:212.62,219.89 4 1 +mymodule/main.go:219.89,221.10 1 1 +mymodule/main.go:222.9,222.15 1 1 +mymodule/main.go:225.5,225.26 1 1 +mymodule/main.go:230.100,235.2 2 1 +mymodule/main.go:238.71,244.19 4 1 +mymodule/main.go:244.19,247.6 1 1 +mymodule/main.go:248.5,248.19 1 1 +mymodule/main.go:252.52,257.21 3 1 +mymodule/main.go:257.21,259.105 2 1 +mymodule/main.go:259.105,261.10 1 1 +mymodule/main.go:262.9,262.42 1 1 +mymodule/main.go:265.5,265.38 1 1 +mymodule/main.go:265.38,267.6 1 1 +mymodule/main.go:269.5,269.24 1 1 +mymodule/main.go:273.46,274.56 1 1 +mymodule/main.go:274.56,276.6 1 1 +mymodule/main.go:277.5,277.15 1 1 +mymodule/main.go:281.40,283.47 1 1 +mymodule/main.go:283.47,285.6 1 1 +mymodule/main.go:286.5,286.15 1 1 +mymodule/main.go:290.71,296.20 3 1 +mymodule/main.go:296.20,300.6 2 1 +mymodule/main.go:303.5,312.19 3 1 +mymodule/main.go:312.19,316.6 2 1 +mymodule/main.go:317.5,321.19 3 1 +mymodule/main.go:321.19,325.6 2 1 +mymodule/main.go:328.5,328.47 1 1 +mymodule/main.go:332.58,337.21 3 1 +mymodule/main.go:337.21,339.187 2 1 +mymodule/main.go:339.187,341.10 1 1 +mymodule/main.go:342.9,342.36 1 1 +mymodule/main.go:345.5,345.38 1 1 +mymodule/main.go:345.38,347.6 1 1 +mymodule/main.go:349.5,349.22 1 1 +mymodule/main.go:353.69,357.20 3 1 +mymodule/main.go:357.20,360.6 2 1 +mymodule/main.go:362.5,379.19 3 1 +mymodule/main.go:379.19,382.6 2 1 +mymodule/main.go:383.5,386.19 3 1 +mymodule/main.go:386.19,389.6 2 1 +mymodule/main.go:391.5,391.45 1 1 +mymodule/main.go:396.68,405.19 4 1 +mymodule/main.go:405.19,408.6 2 1 +mymodule/main.go:409.5,412.19 3 1 +mymodule/main.go:412.19,415.6 2 1 +mymodule/main.go:417.5,417.47 1 1 +mymodule/main.go:421.69,440.19 4 1 +mymodule/main.go:440.19,443.6 2 1 +mymodule/main.go:445.5,446.19 2 1 +mymodule/main.go:446.19,449.6 2 1 +mymodule/main.go:451.5,451.45 1 1 +mymodule/main.go:455.76,466.19 4 1 +mymodule/main.go:466.19,470.6 3 1 +mymodule/main.go:471.5,474.19 3 1 +mymodule/main.go:474.19,478.6 3 1 +mymodule/main.go:480.5,480.55 1 1 +mymodule/main.go:484.76,488.19 3 1 +mymodule/main.go:488.19,491.6 2 1 +mymodule/main.go:493.5,502.19 3 1 +mymodule/main.go:502.19,505.6 2 1 +mymodule/main.go:506.5,509.19 3 1 +mymodule/main.go:509.19,512.6 2 1 +mymodule/main.go:514.5,514.54 1 1 +mymodule/main.go:518.63,521.21 2 1 +mymodule/main.go:521.21,523.144 2 1 +mymodule/main.go:523.144,525.10 1 0 +mymodule/main.go:526.9,526.62 1 1 +mymodule/main.go:529.5,529.38 1 1 +mymodule/main.go:529.38,531.6 1 1 +mymodule/main.go:533.5,533.32 1 1 +mymodule/main.go:537.69,541.19 3 1 +mymodule/main.go:541.19,544.6 2 1 +mymodule/main.go:546.5,562.19 3 1 +mymodule/main.go:562.19,565.6 2 1 +mymodule/main.go:566.5,569.20 3 1 +mymodule/main.go:569.20,570.187 1 1 +mymodule/main.go:570.187,573.10 2 1 +mymodule/main.go:574.11,577.6 2 1 +mymodule/main.go:579.5,579.44 1 1 +mymodule/main.go:584.80,586.16 2 1 +mymodule/main.go:586.16,589.3 2 1 +mymodule/main.go:591.2,599.16 3 1 +mymodule/main.go:599.16,602.3 2 1 +mymodule/main.go:603.2,606.53 3 1 +mymodule/main.go:606.53,609.3 2 1 +mymodule/main.go:611.2,611.27 1 1 +mymodule/main.go:611.27,614.3 2 1 +mymodule/main.go:616.2,616.48 1 1 +mymodule/main.go:619.64,620.21 1 1 +mymodule/main.go:620.21,622.105 2 1 +mymodule/main.go:622.105,624.10 1 1 +mymodule/main.go:625.9,625.56 1 1 +mymodule/main.go:627.5,627.22 1 1 +mymodule/main.go:631.75,635.16 3 1 +mymodule/main.go:635.16,638.3 2 1 +mymodule/main.go:639.2,642.53 3 1 +mymodule/main.go:642.53,645.3 2 1 +mymodule/main.go:647.2,647.48 1 1 +mymodule/main.go:655.72,658.36 2 1 +mymodule/main.go:658.36,661.6 2 1 +mymodule/main.go:663.5,664.19 2 1 +mymodule/main.go:664.19,667.6 2 1 +mymodule/main.go:669.5,670.19 2 1 +mymodule/main.go:670.19,673.6 2 1 +mymodule/main.go:674.5,682.52 6 1 +mymodule/main.go:682.52,685.6 2 1 +mymodule/main.go:687.5,688.19 2 1 +mymodule/main.go:688.19,691.6 2 1 +mymodule/main.go:692.5,694.48 2 1 +mymodule/main.go:694.48,697.6 2 1 +mymodule/main.go:699.5,700.70 2 1 +mymodule/main.go:700.70,703.6 2 1 +mymodule/main.go:705.5,706.66 2 1 +mymodule/main.go:712.67,715.36 2 1 +mymodule/main.go:715.36,718.6 2 1 +mymodule/main.go:720.5,721.67 2 1 +mymodule/main.go:721.67,724.6 2 1 +mymodule/main.go:725.5,727.54 2 1 +mymodule/main.go:727.54,730.6 2 1 +mymodule/main.go:732.5,734.19 3 1 +mymodule/main.go:734.19,737.6 2 1 +mymodule/main.go:739.5,740.30 2 1 +mymodule/main.go:740.30,743.6 2 1 +mymodule/main.go:745.5,749.59 4 1 +mymodule/main.go:749.59,752.6 2 1 +mymodule/main.go:759.70,762.36 2 1 +mymodule/main.go:762.36,765.6 2 1 +mymodule/main.go:767.5,768.19 2 1 +mymodule/main.go:768.19,771.6 2 1 +mymodule/main.go:773.5,774.19 2 1 +mymodule/main.go:774.19,777.6 2 1 +mymodule/main.go:778.5,783.54 4 1 +mymodule/main.go:783.54,786.6 2 1 +mymodule/main.go:788.5,789.19 2 1 +mymodule/main.go:789.19,792.6 2 1 +mymodule/main.go:793.5,795.48 2 1 +mymodule/main.go:795.48,798.6 2 1 +mymodule/main.go:800.5,801.68 2 1 +mymodule/main.go:801.68,804.6 2 1 +mymodule/main.go:806.5,807.66 2 1 +mymodule/main.go:811.65,814.36 2 1 +mymodule/main.go:814.36,817.6 2 1 +mymodule/main.go:819.5,820.65 2 1 +mymodule/main.go:820.65,823.6 2 1 +mymodule/main.go:824.5,826.50 2 1 +mymodule/main.go:826.50,829.6 2 1 +mymodule/main.go:831.5,833.19 3 1 +mymodule/main.go:833.19,836.6 2 1 +mymodule/main.go:838.5,839.30 2 1 +mymodule/main.go:839.30,842.6 2 1 +mymodule/main.go:844.5,847.63 4 1 +mymodule/main.go:847.63,850.6 2 1 +mymodule/main.go:853.71,854.33 1 1 +mymodule/main.go:854.33,857.3 2 1 +mymodule/main.go:859.2,860.68 2 1 +mymodule/main.go:860.68,863.3 2 1 +mymodule/main.go:864.2,866.87 2 1 +mymodule/main.go:866.87,869.3 2 1 +mymodule/main.go:871.2,873.16 3 1 +mymodule/main.go:873.16,877.3 3 1 +mymodule/main.go:879.2,880.27 2 1 +mymodule/main.go:880.27,884.3 3 1 +mymodule/main.go:886.5,888.84 3 1 +mymodule/main.go:888.84,892.6 3 1 +mymodule/main.go:898.68,899.33 1 1 +mymodule/main.go:899.33,902.3 2 1 +mymodule/main.go:904.2,909.16 3 1 +mymodule/main.go:909.16,912.3 2 1 +mymodule/main.go:914.2,914.62 1 1 +mymodule/main.go:914.62,917.3 2 1 +mymodule/main.go:919.2,921.16 3 1 +mymodule/main.go:921.16,925.3 3 1 +mymodule/main.go:926.2,926.16 1 1 +mymodule/main.go:926.16,929.3 2 1 +mymodule/main.go:931.2,932.16 2 1 +mymodule/main.go:932.16,936.3 3 1 +mymodule/main.go:938.2,939.16 2 1 +mymodule/main.go:939.16,943.3 3 1 +mymodule/main.go:945.2,947.61 3 1 +mymodule/main.go:951.76,952.33 1 1 +mymodule/main.go:952.33,955.3 2 1 +mymodule/main.go:957.2,962.16 3 1 +mymodule/main.go:962.16,965.3 2 1 +mymodule/main.go:967.2,967.62 1 1 +mymodule/main.go:967.62,970.3 2 1 +mymodule/main.go:972.2,974.16 3 1 +mymodule/main.go:974.16,975.27 1 1 +mymodule/main.go:975.27,977.4 1 1 +mymodule/main.go:977.9,980.4 2 1 +mymodule/main.go:981.3,981.9 1 1 +mymodule/main.go:984.2,984.17 1 1 +mymodule/main.go:984.17,987.3 2 1 mymodule/main.go:989.2,990.16 2 1 mymodule/main.go:990.16,994.3 3 1 -mymodule/main.go:996.2,998.61 3 1 -mymodule/main.go:1002.70,1003.66 1 1 -mymodule/main.go:1003.66,1006.6 2 1 -mymodule/main.go:1008.5,1009.19 2 1 -mymodule/main.go:1009.19,1012.6 2 1 -mymodule/main.go:1014.5,1015.67 2 1 -mymodule/main.go:1015.67,1018.6 2 1 -mymodule/main.go:1019.5,1021.56 2 1 -mymodule/main.go:1021.56,1024.6 2 1 -mymodule/main.go:1026.5,1033.19 3 1 -mymodule/main.go:1033.19,1036.6 2 1 -mymodule/main.go:1038.5,1039.19 2 1 -mymodule/main.go:1039.19,1042.6 2 1 -mymodule/main.go:1043.5,1043.26 1 1 -mymodule/main.go:1043.26,1046.6 2 1 -mymodule/main.go:1048.5,1048.99 1 1 -mymodule/main.go:1052.68,1053.66 1 1 -mymodule/main.go:1053.66,1056.6 2 1 -mymodule/main.go:1058.5,1059.19 2 1 -mymodule/main.go:1059.19,1062.6 2 1 -mymodule/main.go:1064.5,1065.65 2 1 -mymodule/main.go:1065.65,1068.6 2 1 -mymodule/main.go:1069.5,1071.50 2 1 -mymodule/main.go:1071.50,1074.6 2 1 -mymodule/main.go:1076.5,1083.19 3 1 -mymodule/main.go:1083.19,1086.6 2 1 -mymodule/main.go:1088.5,1089.19 2 1 -mymodule/main.go:1089.19,1092.6 2 1 -mymodule/main.go:1093.5,1093.26 1 1 -mymodule/main.go:1093.26,1096.6 2 1 -mymodule/main.go:1098.5,1098.97 1 1 -mymodule/main.go:1103.74,1104.66 1 1 -mymodule/main.go:1104.66,1107.6 2 1 -mymodule/main.go:1109.5,1110.19 2 1 -mymodule/main.go:1110.19,1113.6 2 1 -mymodule/main.go:1115.5,1116.71 2 1 -mymodule/main.go:1116.71,1119.6 2 1 -mymodule/main.go:1120.5,1122.62 2 1 -mymodule/main.go:1122.62,1125.6 2 1 -mymodule/main.go:1127.5,1134.19 3 1 -mymodule/main.go:1134.19,1137.6 2 1 -mymodule/main.go:1139.5,1140.19 2 1 -mymodule/main.go:1140.19,1143.6 2 1 -mymodule/main.go:1144.5,1144.26 1 1 -mymodule/main.go:1144.26,1147.6 2 1 -mymodule/main.go:1149.5,1149.103 1 1 -mymodule/main.go:1153.58,1154.90 1 1 -mymodule/main.go:1154.90,1156.6 1 1 -mymodule/main.go:1157.5,1157.15 1 1 -mymodule/main.go:1161.70,1162.35 1 1 -mymodule/main.go:1162.35,1165.3 2 1 -mymodule/main.go:1167.2,1168.16 2 1 -mymodule/main.go:1168.16,1171.3 2 1 -mymodule/main.go:1173.2,1175.16 3 1 -mymodule/main.go:1175.16,1178.3 2 1 -mymodule/main.go:1180.2,1180.18 1 1 -mymodule/main.go:1180.18,1183.3 2 1 -mymodule/main.go:1185.2,1186.16 2 1 -mymodule/main.go:1186.16,1189.3 2 1 -mymodule/main.go:1191.2,1191.65 1 1 -mymodule/main.go:1191.65,1194.3 2 1 -mymodule/main.go:1196.2,1196.48 1 1 -mymodule/main.go:1200.68,1201.35 1 1 -mymodule/main.go:1201.35,1204.3 2 1 -mymodule/main.go:1206.2,1207.16 2 1 -mymodule/main.go:1207.16,1210.3 2 1 -mymodule/main.go:1212.2,1214.16 3 1 -mymodule/main.go:1214.16,1218.3 3 1 +mymodule/main.go:997.2,998.16 2 1 +mymodule/main.go:998.16,1002.3 3 1 +mymodule/main.go:1004.2,1006.61 3 1 +mymodule/main.go:1010.70,1011.66 1 1 +mymodule/main.go:1011.66,1014.6 2 1 +mymodule/main.go:1016.5,1017.19 2 1 +mymodule/main.go:1017.19,1020.6 2 1 +mymodule/main.go:1022.5,1023.67 2 1 +mymodule/main.go:1023.67,1026.6 2 1 +mymodule/main.go:1027.5,1029.56 2 1 +mymodule/main.go:1029.56,1032.6 2 1 +mymodule/main.go:1034.5,1041.19 3 1 +mymodule/main.go:1041.19,1044.6 2 1 +mymodule/main.go:1046.5,1047.19 2 1 +mymodule/main.go:1047.19,1050.6 2 1 +mymodule/main.go:1051.5,1051.26 1 1 +mymodule/main.go:1051.26,1054.6 2 1 +mymodule/main.go:1056.5,1056.99 1 1 +mymodule/main.go:1060.68,1061.66 1 1 +mymodule/main.go:1061.66,1064.6 2 1 +mymodule/main.go:1066.5,1067.19 2 1 +mymodule/main.go:1067.19,1070.6 2 1 +mymodule/main.go:1072.5,1073.65 2 1 +mymodule/main.go:1073.65,1076.6 2 1 +mymodule/main.go:1077.5,1079.50 2 1 +mymodule/main.go:1079.50,1082.6 2 1 +mymodule/main.go:1084.5,1091.19 3 1 +mymodule/main.go:1091.19,1094.6 2 1 +mymodule/main.go:1096.5,1097.19 2 1 +mymodule/main.go:1097.19,1100.6 2 1 +mymodule/main.go:1101.5,1101.26 1 1 +mymodule/main.go:1101.26,1104.6 2 1 +mymodule/main.go:1106.5,1106.97 1 1 +mymodule/main.go:1111.74,1112.66 1 1 +mymodule/main.go:1112.66,1115.6 2 1 +mymodule/main.go:1117.5,1118.19 2 1 +mymodule/main.go:1118.19,1121.6 2 1 +mymodule/main.go:1123.5,1124.71 2 1 +mymodule/main.go:1124.71,1127.6 2 1 +mymodule/main.go:1128.5,1130.62 2 1 +mymodule/main.go:1130.62,1133.6 2 1 +mymodule/main.go:1135.5,1142.19 3 1 +mymodule/main.go:1142.19,1145.6 2 1 +mymodule/main.go:1147.5,1148.19 2 1 +mymodule/main.go:1148.19,1151.6 2 1 +mymodule/main.go:1152.5,1152.26 1 1 +mymodule/main.go:1152.26,1155.6 2 1 +mymodule/main.go:1157.5,1157.103 1 1 +mymodule/main.go:1161.58,1162.90 1 1 +mymodule/main.go:1162.90,1164.6 1 1 +mymodule/main.go:1165.5,1165.15 1 1 +mymodule/main.go:1169.70,1170.35 1 1 +mymodule/main.go:1170.35,1173.3 2 1 +mymodule/main.go:1175.2,1176.16 2 1 +mymodule/main.go:1176.16,1179.3 2 1 +mymodule/main.go:1181.2,1183.16 3 1 +mymodule/main.go:1183.16,1186.3 2 1 +mymodule/main.go:1188.2,1188.18 1 1 +mymodule/main.go:1188.18,1191.3 2 1 +mymodule/main.go:1193.2,1194.16 2 1 +mymodule/main.go:1194.16,1197.3 2 1 +mymodule/main.go:1199.2,1199.65 1 1 +mymodule/main.go:1199.65,1202.3 2 1 +mymodule/main.go:1204.2,1204.48 1 1 +mymodule/main.go:1208.68,1209.35 1 1 +mymodule/main.go:1209.35,1212.3 2 1 +mymodule/main.go:1214.2,1215.16 2 1 +mymodule/main.go:1215.16,1218.3 2 1 mymodule/main.go:1220.2,1222.16 3 1 mymodule/main.go:1222.16,1226.3 3 1 -mymodule/main.go:1228.2,1229.16 2 1 -mymodule/main.go:1229.16,1233.3 3 1 -mymodule/main.go:1235.2,1236.23 2 1 -mymodule/main.go:1236.23,1239.3 2 1 -mymodule/main.go:1241.2,1241.24 1 1 -mymodule/main.go:1241.24,1243.17 2 1 -mymodule/main.go:1243.17,1247.4 3 1 -mymodule/main.go:1250.2,1250.46 1 1 -mymodule/main.go:1254.74,1255.35 1 1 -mymodule/main.go:1255.35,1258.3 2 1 -mymodule/main.go:1260.2,1261.16 2 1 -mymodule/main.go:1261.16,1264.3 2 1 -mymodule/main.go:1266.2,1267.16 2 1 -mymodule/main.go:1267.16,1270.3 2 1 -mymodule/main.go:1272.2,1273.23 2 1 -mymodule/main.go:1273.23,1276.3 2 1 -mymodule/main.go:1278.2,1278.52 1 1 +mymodule/main.go:1228.2,1230.16 3 1 +mymodule/main.go:1230.16,1234.3 3 1 +mymodule/main.go:1236.2,1237.16 2 1 +mymodule/main.go:1237.16,1241.3 3 1 +mymodule/main.go:1243.2,1244.23 2 1 +mymodule/main.go:1244.23,1247.3 2 1 +mymodule/main.go:1249.2,1249.24 1 1 +mymodule/main.go:1249.24,1251.17 2 1 +mymodule/main.go:1251.17,1255.4 3 1 +mymodule/main.go:1258.2,1258.46 1 1 +mymodule/main.go:1262.74,1263.35 1 1 +mymodule/main.go:1263.35,1266.3 2 1 +mymodule/main.go:1268.2,1269.16 2 1 +mymodule/main.go:1269.16,1272.3 2 1 +mymodule/main.go:1274.2,1275.16 2 1 +mymodule/main.go:1275.16,1278.3 2 1 +mymodule/main.go:1280.2,1281.23 2 1 +mymodule/main.go:1281.23,1284.3 2 1 +mymodule/main.go:1286.2,1286.52 1 1 diff --git a/api/main.go b/api/main.go index b7122a9..91889f7 100644 --- a/api/main.go +++ b/api/main.go @@ -216,13 +216,16 @@ func RespondWithJSON(w http.ResponseWriter, status int, payload interface{}) { // Set status to 500 w.WriteHeader(http.StatusInternalServerError) // Write the error message, including a newline - w.Write([]byte("Error encoding response\n")) + if _, writeErr := w.Write([]byte("Error encoding response\n")); writeErr != nil { + log.Printf("Error writing response: %v", writeErr) + } return } // Set the status code w.WriteHeader(status) } + // HandleError handles errors by logging them and sending an appropriate HTTP response func HandleError(w http.ResponseWriter, logger *log.Logger, message string, err error, status int) { // Log the error message with additional context @@ -846,6 +849,7 @@ func (app *App) AddBook(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error encoding response", http.StatusInternalServerError) } } + // AddSubscriber adds a new subscriber to the database func (app *App) AddSubscriber(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -880,12 +884,16 @@ func (app *App) AddSubscriber(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) - json.NewEncoder(w).Encode(map[string]int{"id": int(id)}) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + if err := json.NewEncoder(w).Encode(map[string]int{"id": int(id)}); err != nil { + app.Logger.Printf("Error encoding JSON response: %v", err) + w.WriteHeader(http.StatusInternalServerError) + return + } + } - // BorrowBook handles borrowing a book by a subscriber func (app *App) BorrowBook(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { diff --git a/api/main_test.go b/api/main_test.go index 758ceb4..3197210 100644 --- a/api/main_test.go +++ b/api/main_test.go @@ -256,6 +256,35 @@ func TestRespondWithJSON_Error(t *testing.T) { assert.Equal(t, "Error encoding response\n", rr.Body.String(), "Expected error message in response") } +type ErrorWriter struct { + HeaderMap http.Header + StatusCode int +} + +func (e *ErrorWriter) Header() http.Header { + if e.HeaderMap == nil { + e.HeaderMap = make(http.Header) + } + return e.HeaderMap +} + +func (e *ErrorWriter) Write([]byte) (int, error) { + return 0, fmt.Errorf("simulated write error") +} + +func (e *ErrorWriter) WriteHeader(statusCode int) { + e.StatusCode = statusCode +} + +// Test for error handling in RespondWithJSON +func TestRespondWithJSON_WriteError(t *testing.T) { + writer := &ErrorWriter{} + payload := map[string]string{"message": "test"} + + RespondWithJSON(writer, http.StatusOK, payload) + +} + // TestHandleError tests the HandleError function func TestHandleError(t *testing.T) { rr := httptest.NewRecorder() @@ -2040,33 +2069,50 @@ func TestAddBook_InvalidMethod(t *testing.T) { assert.Contains(t, rr.Body.String(), "Only POST method is supported") } -// TestAddSubscriber tests the AddSubscriber handler func TestAddSubscriber_Success(t *testing.T) { - app, mock := createTestApp(t) - defer app.DB.Close() + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("An error '%s' was not expected when opening a stub database connection", err) + } + defer db.Close() - subscriber := Subscriber{Firstname: "John", Lastname: "Doe", Email: "john.doe@example.com"} - body, err := json.Marshal(subscriber) - assert.NoError(t, err) + app := &App{ + DB: db, + Logger: log.New(os.Stdout, "test: ", log.LstdFlags), + } - req := httptest.NewRequest("POST", "/subscribers/new", bytes.NewBuffer(body)) - req.Header.Set("Content-Type", "application/json") + mock.ExpectExec("INSERT INTO subscribers").WillReturnResult(sqlmock.NewResult(1, 1)) - rr := httptest.NewRecorder() + body := bytes.NewBuffer([]byte(`{"firstname": "John", "lastname": "Doe", "email": "john.doe@example.com"}`)) - mock.ExpectExec(`INSERT INTO subscribers \(lastname, firstname, email\) VALUES \(\?, \?, \?\)`). - WithArgs("Doe", "John", "john.doe@example.com"). - WillReturnResult(sqlmock.NewResult(1, 1)) + req, err := http.NewRequest("POST", "/add-subscriber", body) + if err != nil { + t.Fatal(err) + } - handler := http.HandlerFunc(app.AddSubscriber) - handler.ServeHTTP(rr, req) + rr := httptest.NewRecorder() - assert.Equal(t, http.StatusCreated, rr.Code) + handler := http.HandlerFunc(app.AddSubscriber) - var response map[string]int - err = json.NewDecoder(rr.Body).Decode(&response) - assert.NoError(t, err) - assert.Equal(t, 1, response["id"], "Expected inserted subscriber ID to be 1") + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusCreated { + t.Errorf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusCreated) + } + + var response map[string]int + if err := json.NewDecoder(rr.Body).Decode(&response); err != nil { + t.Fatalf("Could not decode response: %v", err) + } + + expected := map[string]int{"id": 1} + if response["id"] != expected["id"] { + t.Errorf("handler returned unexpected body: got %v want %v", response, expected) + } + + if err := mock.ExpectationsWereMet(); err != nil { + t.Errorf("there were unfulfilled expectations: %s", err) + } } func TestAddSubscriber_InvalidJSON(t *testing.T) { @@ -2165,6 +2211,38 @@ func TestAddSubscriber_InvalidMethod(t *testing.T) { assert.Contains(t, rr.Body.String(), "Only POST method is supported") } +func TestAddSubscriber_EncodingError(t *testing.T) { + db, mock, err := sqlmock.New() + if err != nil { + t.Fatalf("An error '%s' was not expected when opening a stub database connection", err) + } + defer db.Close() + + app := &App{ + DB: db, + Logger: log.New(os.Stdout, "test: ", log.LstdFlags), + } + + mock.ExpectExec("INSERT INTO subscribers").WillReturnResult(sqlmock.NewResult(1, 1)) + + body := bytes.NewBuffer([]byte(`{"firstname": "John", "lastname": "Doe", "email": "john.doe@example.com"}`)) + + req, err := http.NewRequest("POST", "/add-subscriber", body) + if err != nil { + t.Fatal(err) + } + + rr := &ErrorWriter{} + + handler := http.HandlerFunc(app.AddSubscriber) + + handler.ServeHTTP(rr, req) + + if rr.StatusCode != http.StatusInternalServerError { + t.Errorf("handler returned wrong status code: got %v want %v", rr.StatusCode, http.StatusInternalServerError) + } +} + // TestBorrowBook_Success tests the BorrowBook handler when borrowing is successful func TestBorrowBook_Success(t *testing.T) { app, mock := createTestApp(t)