-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5b974ee
Showing
22 changed files
with
909 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.idea | ||
/shortify | ||
/devzone/mongodb-data | ||
/.config.toml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Shortify | ||
|
||
## Requirements | ||
|
||
- Go 1.14.4 | ||
- MongoDB | ||
|
||
## Building | ||
|
||
```bash | ||
go build ./cmd/shortify | ||
``` | ||
|
||
## Running | ||
|
||
1. Firstly, you need to generate config: | ||
```bash | ||
./shortify -genconfig > backend.toml | ||
``` | ||
|
||
2. Then just edit it, and start executable with specified config: | ||
```bash | ||
./shortify -config ./backend.toml | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package app | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/MoonSHRD/logger" | ||
"net/http" | ||
|
||
"github.com/MoonSHRD/shortify/config" | ||
"github.com/gorilla/mux" | ||
"go.mongodb.org/mongo-driver/mongo" | ||
"go.mongodb.org/mongo-driver/mongo/options" | ||
) | ||
|
||
type App struct { | ||
Config *config.Config | ||
DBClient *mongo.Client | ||
DB *mongo.Database | ||
|
||
server *http.Server | ||
} | ||
|
||
func NewApp(config *config.Config) (*App, error) { | ||
app := &App{} | ||
app.Config = config | ||
err := app.createMongoDBConnection(&config.MongoDB) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
port := app.Config.HTTP.Port | ||
addr := app.Config.HTTP.Address | ||
server := &http.Server{Addr: fmt.Sprintf("%s:%d", addr, port)} | ||
app.server = server | ||
|
||
return app, nil | ||
} | ||
|
||
func (app *App) createMongoDBConnection(config *config.MongoDB) error { | ||
var mongoURI string | ||
if config.User == "" && config.Password == "" { | ||
mongoURI = fmt.Sprintf("mongodb://%s:%d", config.Host, config.Port) | ||
} else { | ||
mongoURI = fmt.Sprintf("mongodb://%s:%s@%s:%d", config.User, config.Password, config.Host, config.Port) | ||
} | ||
clientOptions := options.Client().ApplyURI(mongoURI) | ||
client, err := mongo.Connect(context.Background(), clientOptions) | ||
if err != nil { | ||
return err | ||
} | ||
err = client.Ping(context.Background(), nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
app.DBClient = client | ||
app.DB = client.Database(app.Config.MongoDB.DatabaseName) | ||
return nil | ||
} | ||
|
||
func (app *App) Run(r *mux.Router) { | ||
port := app.Config.HTTP.Port | ||
addr := app.Config.HTTP.Address | ||
app.server.Handler = r | ||
|
||
logger.Infof("HTTP server starts listening at %s:%d", addr, port) | ||
go func() { | ||
if err := app.server.ListenAndServe(); err != nil { | ||
logger.Info(err) | ||
} | ||
}() | ||
} | ||
|
||
func (app *App) Destroy() { | ||
ctx := context.Background() | ||
_ = app.DBClient.Disconnect(ctx) | ||
_ = app.server.Shutdown(ctx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
|
||
"github.com/MoonSHRD/logger" | ||
"github.com/MoonSHRD/shortify/app" | ||
"github.com/MoonSHRD/shortify/config" | ||
"github.com/MoonSHRD/shortify/router" | ||
) | ||
|
||
func main() { | ||
var configPath string | ||
var generateConfig bool | ||
var verboseLogging bool | ||
var syslogLogging bool | ||
flag.StringVar(&configPath, "config", "", "Path to server config") | ||
flag.BoolVar(&generateConfig, "genconfig", false, "Generate new config") | ||
flag.BoolVar(&verboseLogging, "verbose", true, "Verbose logging") | ||
flag.BoolVar(&syslogLogging, "syslog", false, "Log to system logging daemon") | ||
flag.Parse() | ||
defer logger.Init("shortify", verboseLogging, syslogLogging, ioutil.Discard).Close() // TODO Make ability to use file for log output | ||
if generateConfig { | ||
confStr, err := config.Generate() | ||
if err != nil { | ||
log.Fatalf("Cannot generate config! %s", err.Error()) | ||
} | ||
fmt.Print(confStr) | ||
os.Exit(0) | ||
} | ||
logger.Info("Starting Shortify...") | ||
if configPath == "" { | ||
logger.Fatal("Path to config isn't specified!") | ||
} | ||
|
||
cfg, err := config.Parse(configPath) | ||
if err != nil { | ||
logger.Fatal(err) | ||
} | ||
app, err := app.NewApp(cfg) | ||
if err != nil { | ||
logger.Fatal(err) | ||
} | ||
router, err := router.NewRouter(app) | ||
if err != nil { | ||
logger.Fatalf("Failed to initialize router: %s", err.Error()) | ||
} | ||
|
||
// CTRL+C handler. | ||
signalHandler := make(chan os.Signal, 1) | ||
shutdownDone := make(chan bool, 1) | ||
signal.Notify(signalHandler, os.Interrupt, syscall.SIGTERM) | ||
go func() { | ||
<-signalHandler | ||
logger.Info("CTRL+C or SIGTERM received, shutting down Shortify...") | ||
app.Destroy() | ||
shutdownDone <- true | ||
}() | ||
|
||
app.Run(router) | ||
|
||
<-shutdownDone | ||
os.Exit(0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package config | ||
|
||
import ( | ||
"github.com/pelletier/go-toml" | ||
"log" | ||
"os" | ||
) | ||
|
||
type Config struct { | ||
HTTP HTTP `toml:"http"` | ||
MongoDB MongoDB `toml:"mongoDB"` | ||
AuthServerURL string `toml:"authServerURL"` | ||
} | ||
|
||
type HTTP struct { | ||
Address string `toml:"address"` | ||
Port int `toml:"port"` | ||
} | ||
|
||
type MongoDB struct { | ||
Host string `toml:"host"` | ||
Port int `toml:"port"` | ||
User string `toml:"user"` | ||
Password string `toml:"password"` | ||
DatabaseName string `toml:"databaseName"` | ||
} | ||
|
||
func Parse(path string) (*Config, error) { | ||
file, err := os.Open(path) | ||
defer file.Close() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
decoder := toml.NewDecoder(file) | ||
cfg := Config{} | ||
err = decoder.Decode(&cfg) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
return &cfg, nil | ||
} | ||
|
||
func Generate() (string, error) { | ||
config := Config{} | ||
configStr, err := toml.Marshal(config) | ||
if err != nil { | ||
return "", err | ||
} | ||
return string(configStr), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package controllers | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/MoonSHRD/logger" | ||
"net/http" | ||
|
||
"github.com/MoonSHRD/shortify/app" | ||
httpModels "github.com/MoonSHRD/shortify/models/http" | ||
"github.com/MoonSHRD/shortify/services" | ||
) | ||
|
||
type LinksController struct { | ||
app *app.App | ||
linksService *services.LinksService | ||
} | ||
|
||
func NewLinksController(a *app.App, ls *services.LinksService) *LinksController { | ||
return &LinksController{ | ||
app: a, | ||
linksService: ls, | ||
} | ||
} | ||
|
||
func (lc *LinksController) CreateLink(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
decoder := json.NewDecoder(r.Body) | ||
var createLinkRequest httpModels.CreateLinkRequest | ||
err := decoder.Decode(&createLinkRequest) | ||
if err != nil { | ||
logger.Error(err) | ||
ReturnHTTPError(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
res, err := lc.linksService.Put(&createLinkRequest) | ||
if err != nil { | ||
if err == services.ErrEmptyLinkValue { | ||
ReturnHTTPError(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
logger.Error(err) | ||
ReturnHTTPError(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
json, _ := json.Marshal(res) | ||
w.Write(json) | ||
} | ||
|
||
func (lc *LinksController) GetLink(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("Content-Type", "application/json") | ||
|
||
linkIDParam, ok := r.URL.Query()["linkID"] | ||
if !ok || len(linkIDParam[0]) < 1 { | ||
logger.Error("Url Param 'linkID' is missing") | ||
return | ||
} | ||
linkID := linkIDParam[0] | ||
|
||
res, err := lc.linksService.GetByLinkID(linkID) | ||
if err != nil { | ||
if err == services.ErrNoSuchLink { | ||
ReturnHTTPError(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
logger.Error(err) | ||
ReturnHTTPError(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
json, _ := json.Marshal(res) | ||
w.Write(json) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package controllers | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
httpModels "github.com/MoonSHRD/shortify/models/http" | ||
) | ||
|
||
func ReturnHTTPError(w http.ResponseWriter, err string, code int) { | ||
res := httpModels.HTTPError{ | ||
Error: httpModels.ErrorMessage{ | ||
Message: err, | ||
}, | ||
} | ||
r, _ := json.Marshal(res) | ||
writeHTTPJSONError(w, string(r), code) | ||
} | ||
|
||
func writeHTTPJSONError(w http.ResponseWriter, err string, code int) { | ||
w.Header().Set("Content-Type", "application/json; charset=utf-8") | ||
w.Header().Set("X-Content-Type-Options", "nosniff") | ||
w.WriteHeader(code) | ||
fmt.Fprintln(w, err) | ||
} |
Oops, something went wrong.