Skip to content

Commit 938abae

Browse files
committed
add movies code
1 parent 1f4467c commit 938abae

File tree

7 files changed

+213
-1
lines changed

7 files changed

+213
-1
lines changed

movies/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -a -installsuffix cgo -o
1111

1212
# build a small image
1313
FROM alpine:3.17.3
14-
LABEL language="golang"
14+
LABEL language "golang"
1515
LABEL org.opencontainers.image.source https://github.com/mikebellcoder/microservices-docker-go-mongodb
1616
COPY --from=builder /etc/passwd /etc/passwd
1717
COPY --from=builder --chown=elf:1000 /go/bin/cinema-movies /cinema

movies/cmd/app/handlers.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
7+
"github.com/gorilla/mux"
8+
"github.com/mikebellcoder/microservices-docker-go-mongodb/movies/pkg/models"
9+
)
10+
11+
func (app *application) all(w http.ResponseWriter, r *http.Request) {
12+
// Get all movies stored
13+
movies, err := app.movies.All()
14+
if err != nil {
15+
app.serverError(w, err)
16+
}
17+
18+
// Convert movie list into json encoding
19+
b, err := json.Marshal(movies)
20+
if err != nil {
21+
app.serverError(w, err)
22+
}
23+
24+
app.infoLog.Println("Movies have been listed")
25+
26+
// Send response back
27+
w.Header().Set("Content-Type", "application/json")
28+
w.WriteHeader(http.StatusOK)
29+
w.Write(b)
30+
}
31+
32+
func (app *application) findByID(w http.ResponseWriter, r *http.Request) {
33+
// Get id from incoming url
34+
vars := mux.Vars(r)
35+
id := vars["id"]
36+
37+
// Find movie by id
38+
m, err := app.movies.FindByID(id)
39+
if err != nil {
40+
if err.Error() == "ErrNoDocuments" { // TODO make this string a constant
41+
app.infoLog.Println("Movie not found")
42+
return
43+
}
44+
// Any other error will send an internal server error
45+
app.serverError(w, err)
46+
}
47+
48+
// Convert movie to json encoding
49+
b, err := json.Marshal(m)
50+
if err != nil {
51+
app.serverError(w, err)
52+
}
53+
54+
app.infoLog.Println("Have found a movie")
55+
56+
// Send response back
57+
w.Header().Set("Content-Type", "application/json")
58+
w.WriteHeader(http.StatusOK)
59+
w.Write(b)
60+
}
61+
62+
func (app *application) insert(w http.ResponseWriter, r *http.Request) {
63+
// Define movie model
64+
var m models.Movie
65+
// Get request information
66+
err := json.NewDecoder(r.Body).Decode(&m)
67+
if err != nil {
68+
app.serverError(w, err)
69+
}
70+
71+
// Insert new movie
72+
insertResult, err := app.movies.Insert(m)
73+
if err != nil {
74+
app.serverError(w, err)
75+
}
76+
77+
app.infoLog.Printf("New movie has been created, id=%s\n", insertResult.InsertedID)
78+
}
79+
80+
func (app *application) delete(w http.ResponseWriter, r *http.Request) {
81+
// Get id from incoming url
82+
vars := mux.Vars(r)
83+
id := vars["id"]
84+
85+
// Delete movie by id
86+
deleteResult, err := app.movies.Delete(id)
87+
if err != nil {
88+
app.serverError(w, err)
89+
}
90+
91+
app.infoLog.Printf("%d movie(s) have been deleted\n", deleteResult.DeletedCount)
92+
}

movies/cmd/app/helpers.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"runtime/debug"
7+
)
8+
9+
func (app *application) serverError(w http.ResponseWriter, err error) {
10+
trace := fmt.Sprintf("%s\n%s", err.Error(), debug.Stack())
11+
app.erroLog.Output(2, trace)
12+
13+
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
14+
}
15+
16+
func (app *application) clientError(w http.ResponseWriter, status int) {
17+
http.Error(w, http.StatusText(status), status)
18+
}

movies/cmd/app/main.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"flag"
6+
"fmt"
7+
"log"
8+
"net/http"
9+
"os"
10+
"time"
11+
12+
"github.com/mikebellcoder/microservices-docker-go-mongodb/movies/pkg/models/mongodb"
13+
"go.mongodb.org/mongo-driver/mongo"
14+
"go.mongodb.org/mongo-driver/mongo/options"
15+
)
16+
17+
type application struct {
18+
erroLog *log.Logger
19+
infoLog *log.Logger
20+
movies *mongodb.MovieModel
21+
}
22+
23+
func main() {
24+
25+
// Define command-line flags
26+
serverAddr := flag.String("serverAddr", "", "HTTP server network address")
27+
serverPort := flag.Int("serverPort", 4000, "HTTP server network port")
28+
mongoURI := flag.String("mongoURI", "mongodb://localhost:27017", "Database hostname url")
29+
mongoDatabase := flag.String("mongoDatabase", "movies", "Database name")
30+
enableCredentials := flag.Bool("enableCredentials", false, "Enable the use of for mongodb connection")
31+
flag.Parse()
32+
33+
// Create logger for writing information and error messages
34+
infoLog := log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime)
35+
errLog := log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile)
36+
37+
// Create mongo client config
38+
co := options.Client().ApplyURI(*mongoURI)
39+
if *enableCredentials {
40+
co.Auth = &options.Credential{
41+
Username: os.Getenv("MONGODB_USERNAME"),
42+
Password: os.Getenv("MONGODB_PASSWORD"),
43+
}
44+
}
45+
46+
// Establish database connection
47+
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
48+
defer cancel()
49+
client, err := mongo.Connect(ctx, co)
50+
if err != nil {
51+
errLog.Fatal(err)
52+
}
53+
54+
defer func() {
55+
if err = client.Disconnect(ctx); err != nil {
56+
panic(err)
57+
}
58+
}()
59+
60+
infoLog.Printf("Database connection established\n")
61+
62+
// Initialize a new instance of a app containing the dependencies
63+
app := &application{
64+
infoLog: infoLog,
65+
erroLog: errLog,
66+
movies: &mongodb.MovieModel{
67+
C: client.Database(*mongoDatabase).Collection("movies"),
68+
},
69+
}
70+
71+
// Initialize a new http.Server struct.
72+
serverURI := fmt.Sprintf("%s:%d", *serverAddr, *serverPort)
73+
srv := &http.Server{
74+
Addr: serverURI,
75+
ErrorLog: errLog,
76+
Handler: app.routes(),
77+
IdleTimeout: time.Minute,
78+
ReadTimeout: 5 * time.Second,
79+
WriteTimeout: 10 * time.Second,
80+
}
81+
82+
infoLog.Printf("Starting server on %s\n", serverURI)
83+
err = srv.ListenAndServe()
84+
errLog.Fatal(err)
85+
}

movies/cmd/app/routes.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package main
2+
3+
import "github.com/gorilla/mux"
4+
5+
func (app *application) routes() *mux.Router {
6+
// Register handler functions.
7+
r := mux.NewRouter()
8+
r.HandleFunc("/api/movies/", app.all).Methods("GET")
9+
r.HandleFunc("/api/movies/{id}", app.findByID).Methods("GET")
10+
r.HandleFunc("/api/movies/", app.insert).Methods("POST")
11+
r.HandleFunc("/api/movies/{id}", app.delete).Methods("DELETE")
12+
13+
return r
14+
}

movies/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.22.5
44

55
require (
66
github.com/golang/snappy v0.0.4 // indirect
7+
github.com/gorilla/mux v1.8.1 // indirect
78
github.com/klauspost/compress v1.16.7 // indirect
89
github.com/montanaflynn/stats v0.7.1 // indirect
910
github.com/xdg-go/pbkdf2 v1.0.0 // indirect

movies/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
22
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
3+
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
4+
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
35
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
46
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
57
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=

0 commit comments

Comments
 (0)