From 996e3efa2660f80e99235e55e8e8bb8504b8039f Mon Sep 17 00:00:00 2001 From: "Schmitt, Max" Date: Wed, 8 Nov 2017 16:52:37 +0100 Subject: [PATCH] - Removing sourcemaps bevore we embed it - removed Service worker - removed unnecessary run.sh (now we have a Makefile) - Cleaned up README.md --- .gitignore | 4 +- Makefile | 2 + README.md | 124 +++++++--------------------- build/schema.json | 3 + run.sh | 3 - static/src/index.js | 1 - static/src/registerServiceWorker.js | 108 ------------------------ 7 files changed, 37 insertions(+), 208 deletions(-) delete mode 100644 run.sh delete mode 100644 static/src/registerServiceWorker.js diff --git a/.gitignore b/.gitignore index 7e83430..e899e3a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,9 @@ main.db debug *db.lock + static/bower_components /config.json static.go -handlers/tmpls/tmpls.go \ No newline at end of file +/handlers/tmpls/tmpls.go +/build/schema.json \ No newline at end of file diff --git a/Makefile b/Makefile index ceea1fd..f0f34b3 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,7 @@ runUnitTests: buildNodeFrontend: @cd static && yarn install @cd static && yarn build + @cd static && @rm build/static/**/*.map embedFrontend: @cd handlers/tmpls && esc -o tmpls.go -pkg tmpls -include ^*\.tmpl . @@ -21,6 +22,7 @@ getGoDependencies: go get -v ./... buildProject: + @cd build && go build schema.go && ./schema @mkdir releases gox -output="releases/{{.OS}}_{{.Arch}}/{{.OS}}_{{.Arch}}" find releases -maxdepth 1 -mindepth 1 -type d -exec cp build/config.json {} \; diff --git a/README.md b/README.md index d1d0d8a..bc05a19 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![GoDoc](https://godoc.org/github.com/maxibanki/golang-url-shortener?status.svg)](https://godoc.org/github.com/maxibanki/golang-url-shortener) [![Go Report Card](https://goreportcard.com/badge/github.com/maxibanki/golang-url-shortener)](https://goreportcard.com/report/github.com/maxibanki/golang-url-shortener) [![Coverage Status](https://coveralls.io/repos/github/maxibanki/golang-url-shortener/badge.svg?branch=master)](https://coveralls.io/github/maxibanki/golang-url-shortener?branch=master) -[![License](https://img.shields.io/badge/License-MIT-blue.svg)](http://opensource.org/licenses/MIT) +[![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Waffle.io - Columns and their card count](https://badge.waffle.io/maxibanki/golang-url-shortener.png?columns=all)](https://waffle.io/maxibanki/golang-url-shortener?utm_source=badge) [![Download](https://api.bintray.com/packages/maxibanki/golang-url-shortener/travis-ci/images/download.svg?version=0.1) ](https://bintray.com/maxibanki/golang-url-shortener/travis-ci/0.1/link) @@ -12,125 +12,59 @@ - URL Shortening - Visitor Counting +- Expireable Links - URL deletion -- Authorization System +- Authorization System via OAuth 2.0 from Google (more providers following) - High performance database with [bolt](https://github.com/boltdb/bolt) -- [ShareX](https://github.com/ShareX/ShareX) integration -- Easy Docker Deployment +- Easy [ShareX](https://github.com/ShareX/ShareX) integration +- Dockerizable ## Server Installation ### Standard -Since we don't provide prebuild binaries, you have to build it yourself. For that you need Golang and Git installed on your system. +Download the package for your architecture and operating system from [bintray](https://bintray.com/maxibanki/golang-url-shortener/travis-ci) and extract it. -```bash -git clone https://github.com/maxibanki/golang-url-shortener # Clone repository -cd golang-url-shortener # Go into it -go get -v ./... # Fetch dependencies -go build # Build executable -./golang-url-shortener # Run it -``` +### Docker -### Docker Compose +TODO -Only execute the [docker-compose.yml](docker-compose.yml) and adjust the environment variables to your needs. +## Configuration -### Configuration +The configuration is a JSON file, an example is located [here](build/config.json). If your editor supports intellisense by using a schema (e.g. [VS Code](https://github.com/Microsoft/vscode)) then you can simply press space for auto completion. -The configuration is a yaml based file of key value pairs. It is located in the installation folder and is called `config.yml`: +The config parameters should be really selfexplaning, but here is a detailed description for all of these: -```json -{ - "General": { - "DBPath": "main.db", - "ListenAddr": ":8080", - "ShortedIDLength": 4 - }, - "OAuth": { - "Google": { - "ClientID": "", - "ClientSecret": "" - } - } -} -``` +TODO: Add config parameters + +## OAuth + +### Google + +Visit [console.cloud.google.com](https://console.cloud.google.com), create or use an existing project, goto `APIs & Services` -> `Credentials` and create there an `OAuth Client-ID` for the application type `Webapplicaton`. There you get the Client-ID and ClientSecret for your configuration. It's important, that you set in the Google Cloud Platform `YOUR_URL/api/v1/callback` as authorized redirect URLs. ## Clients ### General -There is a mechanism integrated, that you can call the `POST` endpoints with the following techniques: +In general the `POST` endpoints can be called, by using one of the following techniques: - application/json - application/x-www-form-urlencoded - multipart/form-data -### [ShareX](https://github.com/ShareX/ShareX) Configuration - -This URL Shortener has fully support with ShareX. To use it, just import the configuration to your ShareX. For that you need to open the `Destination settings` => `Other / Custom uploaders` => `Import` => `From Clipboard` menu. - -After you've done this, you need to set it as your standard URL Shortener. For that go back into your main menu => `Destinations` => `URL Shortener` => `Custom URL Shortener`. - -```json -{ - "Name": "Golang URL Shortener", - "DestinationType": "URLShortener", - "RequestType": "POST", - "RequestURL": "http://127.0.0.1:8080/api/v1/create", - "Arguments": { - "URL": "$input$" - }, - "ResponseType": "Text", - "URL": "$json:URL$" -} -``` - -### Curl - -#### Create - -```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", -} -``` +For all the endpoints which have `protected` in her path there is the `Authorization` header required. -#### Info +### [ShareX](https://github.com/ShareX/ShareX) -```bash -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/", - "VisitCount": 1, - "CreatedOn": "2017-10-29T23:35:48.2977548+01:00", - "LastVisit": "2017-10-29T23:36:14.193236+01:00" -} -``` - -### 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 - -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. +For ShareX usage, we refer to the menu item in the frontend where your configuration will be generated. There are further information for the detailled use. ## 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 +Just only because I want to extend my current self hosted URL shorter and learn about new techniques like: + +- Golang unit tests +- React +- Makefiles +- Travis CI +- Key / Value databases \ No newline at end of file diff --git a/build/schema.json b/build/schema.json index 103891c..58f3966 100644 --- a/build/schema.json +++ b/build/schema.json @@ -2,6 +2,9 @@ "$schema": "http://json-schema.org/schema#", "type": "object", "properties": { + "$schema": { + "type": "string" + }, "Handlers": { "type": "object", "properties": { diff --git a/run.sh b/run.sh deleted file mode 100644 index 313f4e2..0000000 --- a/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -go get -v ./... -go run -v main.go diff --git a/static/src/index.js b/static/src/index.js index 7e5acb0..9aaaa23 100644 --- a/static/src/index.js +++ b/static/src/index.js @@ -1,4 +1,3 @@ -// import registerServiceWorker from './registerServiceWorker'; import React, { Component } from 'react' import ReactDOM from 'react-dom'; import { HashRouter, Route, Link } from 'react-router-dom' diff --git a/static/src/registerServiceWorker.js b/static/src/registerServiceWorker.js deleted file mode 100644 index 12542ba..0000000 --- a/static/src/registerServiceWorker.js +++ /dev/null @@ -1,108 +0,0 @@ -// In production, we register a service worker to serve assets from local cache. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the "N+1" visit to a page, since previously -// cached resources are updated in the background. - -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) -); - -export default function register() { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Lets check if a service worker still exists or not. - checkValidServiceWorker(swUrl); - } else { - // Is not local host. Just register service worker - registerValidSW(swUrl); - } - }); - } -} - -function registerValidSW(swUrl) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.'); - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - if ( - response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 - ) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl); - } - }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { - registration.unregister(); - }); - } -}