diff --git a/README.md b/README.md
index f48d9b7..51f1278 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,11 @@
[](http://opensource.org/licenses/MIT)
[](https://waffle.io/maxibanki/golang-url-shortener?utm_source=badge)
-## Main Features:
+## Main Features
- URL Shortening
- Visitor Counting
-- URL deletion
+- URL deletion
- Authorization System
- High performance database with [bolt](https://github.com/boltdb/bolt)
- [ShareX](https://github.com/ShareX/ShareX) integration
@@ -30,11 +30,12 @@ go get -v ./... # Fetch dependencies
go build # Build executable
./golang-url-shortener # Run it
```
+
### Docker Compose
Only execute the [docker-compose.yml](docker-compose.yml) and adjust the environment variables to your needs.
-### Configuration:
+### Configuration
The configuration is a yaml based file of key value pairs. It is located in the installation folder and is called `config.yml`:
@@ -54,11 +55,12 @@ The configuration is a yaml based file of key value pairs. It is located in the
}
```
-## Clients:
+## Clients
### General
There is a mechanism integrated, that you can call the `POST` endpoints with the following techniques:
+
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
@@ -90,6 +92,7 @@ After you've done this, you need to set it as your standard URL Shortener. For t
```bash
curl -X POST -H 'Content-Type: application/json' -d '{"URL":"https://www.google.de/"}' http://127.0.0.1:8080/api/v1/create
```
+
```json
{
"URL": "http://127.0.0.1:8080/dgUV",
@@ -99,8 +102,9 @@ curl -X POST -H 'Content-Type: application/json' -d '{"URL":"https://www.google.
#### Info
```bash
-$ curl -X POST -H 'Content-Type: application/json' -d '{"ID":"dgUV"}' http://127.0.0.1:8080/api/v1/info
+curl -X POST -H 'Content-Type: application/json' -d '{"ID":"dgUV"}' http://127.0.0.1:8080/api/v1/info
```
+
```json
{
"URL": "https://google.com/",
@@ -110,21 +114,22 @@ $ curl -X POST -H 'Content-Type: application/json' -d '{"ID":"dgUV"}' http://127
}
```
-### HTTP Endpoints:
+### HTTP Endpoints
#### `/api/v1/create` POST
Create is the handler for creating entries, you need to provide only an `URL`. The response will always be JSON encoded and contain an URL with the short link.
-#### `/api/v1/info` POST
+#### `/api/v1/info` POST
This handler returns the information about an entry. This includes:
+
- Created At
- Last Visit
- Visitor counter
For that you need to send a field `ID` to the backend.
-## Why did you built this?
+## Why did you built this
Just only because I want to extend my current self hosted URL shorter and learn about new techniques like Go unit testing and react.
\ No newline at end of file
diff --git a/build/schema.go b/build/schema.go
new file mode 100644
index 0000000..9beac86
--- /dev/null
+++ b/build/schema.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "flag"
+ "io/ioutil"
+ "log"
+
+ "github.com/maxibanki/golang-url-shortener/config"
+ "github.com/urakozz/go-json-schema-generator"
+)
+
+func main() {
+ schemaPath := flag.String("path", "schema.json", "location of the converted schema")
+ flag.Parse()
+ schema := generator.Generate(&config.Configuration{})
+ if err := ioutil.WriteFile(*schemaPath, []byte(schema), 644); err != nil {
+ log.Fatalf("could not write schema: %v", err)
+ }
+}
diff --git a/build/schema.json b/build/schema.json
new file mode 100644
index 0000000..103891c
--- /dev/null
+++ b/build/schema.json
@@ -0,0 +1,50 @@
+{
+ "$schema": "http://json-schema.org/schema#",
+ "type": "object",
+ "properties": {
+ "Handlers": {
+ "type": "object",
+ "properties": {
+ "BaseURL": {
+ "type": "string"
+ },
+ "EnableGinDebugMode": {
+ "type": "boolean"
+ },
+ "ListenAddr": {
+ "type": "string"
+ },
+ "OAuth": {
+ "type": "object",
+ "properties": {
+ "Google": {
+ "type": "object",
+ "properties": {
+ "ClientID": {
+ "type": "string"
+ },
+ "ClientSecret": {
+ "type": "string"
+ }
+ }
+ }
+ }
+ },
+ "Secret": {
+ "type": "string"
+ }
+ }
+ },
+ "Store": {
+ "type": "object",
+ "properties": {
+ "DBPath": {
+ "type": "string"
+ },
+ "ShortedIDLength": {
+ "type": "integer"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/config.dist.json b/config.dist.json
new file mode 100644
index 0000000..7b23012
--- /dev/null
+++ b/config.dist.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "./build/schema.json",
+ "Store": {
+ "DBPath": "main.db",
+ "ShortedIDLength": 4
+ },
+ "Handlers": {
+ "ListenAddr": ":8080",
+ "BaseURL": "http://localhost:3000",
+ "EnableGinDebugMode": false,
+ "OAuth": {
+ "Google": {
+ "ClientID": "",
+ "ClientSecret": ""
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/config/config.go b/config/config.go
index 4bde030..0ed5b50 100644
--- a/config/config.go
+++ b/config/config.go
@@ -12,6 +12,7 @@ import (
// Configuration holds all the needed parameters use
// the URL Shortener
type Configuration struct {
+ Schema string `json:"$schema"`
Store Store
Handlers Handlers
}
@@ -19,7 +20,7 @@ type Configuration struct {
// Store contains the needed fields for the Store package
type Store struct {
DBPath string
- ShortedIDLength int
+ ShortedIDLength uint
}
// Handlers contains the needed fields for the Handlers package
diff --git a/static/package.json b/static/package.json
index 0c45543..4790b4a 100644
--- a/static/package.json
+++ b/static/package.json
@@ -9,8 +9,11 @@
}
},
"dependencies": {
+ "highlight.js": "^9.12.0",
"react": "^16.0.0",
+ "react-clipboard.js": "^1.1.2",
"react-dom": "^16.0.0",
+ "react-fast-highlight": "^2.2.0",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.17",
diff --git a/static/src/ShareX/ShareX.js b/static/src/ShareX/ShareX.js
new file mode 100644
index 0000000..cc37a39
--- /dev/null
+++ b/static/src/ShareX/ShareX.js
@@ -0,0 +1,39 @@
+import React, { Component } from 'react'
+import { Container } from 'semantic-ui-react'
+import { Highlight } from 'react-fast-highlight';
+import ClipboardButton from 'react-clipboard.js';
+import 'highlight.js/styles/github.css'
+
+export default class ShareXComponent extends Component {
+ state = {
+ config: JSON.stringify({
+ Name: "Golang URL Shortener",
+ DestinationType: "URLShortener",
+ RequestType: "POST",
+ RequestURL: window.location.origin + "/api/v1/protected/create",
+ Arguments: {
+ URL: "$input$"
+ },
+ Headers: {
+ Authorization: window.localStorage.getItem('token')
+ },
+ ResponseType: "Text",
+ URL: "$json:URL$"
+ }, null, 4)
+ }
+
+ render() {
+ const { config } = this.state
+ return (
+