From 5c005ae8903b8bfd81d0ffed8708716c810ba174 Mon Sep 17 00:00:00 2001 From: Jeff Billimek Date: Tue, 14 Aug 2018 07:04:07 -0400 Subject: [PATCH] configurable app DisplayURL for the UI (#121) * changes to enable custom 'display' URL in app * making example.yml use an empty string for DisplayURL --- config/example.yaml | 3 ++- internal/handlers/handlers.go | 1 + internal/handlers/public.go | 6 ++++++ internal/util/config.go | 7 +++++++ web/src/Home/Home.js | 14 ++++++++------ web/src/Lookup/Lookup.js | 14 ++++++++++---- web/src/Recent/Recent.js | 8 ++++++-- 7 files changed, 40 insertions(+), 13 deletions(-) diff --git a/config/example.yaml b/config/example.yaml index a75d718..7d7caef 100644 --- a/config/example.yaml +++ b/config/example.yaml @@ -1,5 +1,6 @@ ListenAddr: ':8080' # Consists of 'IP:Port', e.g. ':8080' listens on any IP and on Port 8080 -BaseURL: 'http://localhost:3000' # Origin URL, required for the authentication via OAuth +BaseURL: 'http://localhost:3000' # Origin URL, required for the authentication via OAuth callback +DisplayURL: '' # (OPTIONAL) Display URL, how the apication will present itself in the UI - if not set, defaults to BaseURL Backend: boltdb # Can be 'boltdb' or 'redis' DataDir: ./data # Contains: the database and the private key EnableDebugMode: true # Activates more detailed logging diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index cf601c2..c1c27ce 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -163,6 +163,7 @@ func (h *Handler) setHandlers() error { h.engine.GET("/api/v1/info", h.handleInfo) h.engine.GET("/d/:id/:hash", h.handleDelete) h.engine.GET("/ok", h.handleHealthcheck) + h.engine.GET("/displayurl", h.handleDisplayURL) // Handling the shorted URLs, if no one exists, it checks // in the filesystem and sets headers for caching diff --git a/internal/handlers/public.go b/internal/handlers/public.go index 81e1510..fafaa7f 100644 --- a/internal/handlers/public.go +++ b/internal/handlers/public.go @@ -162,6 +162,12 @@ func (h *Handler) handleInfo(c *gin.Context) { c.JSON(http.StatusOK, out) } +// handleDisplayURL returns the URL to use for display purposes +func (h *Handler) handleDisplayURL(c *gin.Context) { + out := util.GetConfig().DisplayURL + c.JSON(http.StatusOK, out) +} + func (h *Handler) handleRecent(c *gin.Context) { user := c.MustGet("user").(*auth.JWTClaims) entries, err := h.store.GetUserEntries(user.OAuthProvider, user.OAuthID) diff --git a/internal/util/config.go b/internal/util/config.go index 42fe6ed..f014366 100644 --- a/internal/util/config.go +++ b/internal/util/config.go @@ -16,6 +16,7 @@ import ( type Configuration struct { ListenAddr string `yaml:"ListenAddr" env:"LISTEN_ADDR"` BaseURL string `yaml:"BaseURL" env:"BASE_URL"` + DisplayURL string `yaml:"DisplayURL" env:"DISPLAY_URL"` DataDir string `yaml:"DataDir" env:"DATA_DIR"` Backend string `yaml:"Backend" env:"BACKEND"` AuthBackend string `yaml:"AuthBackend" env:"AUTH_BACKEND"` @@ -58,6 +59,7 @@ type proxyAuthConf struct { var Config = Configuration{ ListenAddr: ":8080", BaseURL: "http://localhost:3000", + DisplayURL: "", DataDir: "data", Backend: "boltdb", EnableDebugMode: false, @@ -110,6 +112,11 @@ func (o oAuthConf) Enabled() bool { // GetConfig returns the configuration from the memory func GetConfig() Configuration { + // if DisplayURL is not set in the config, default to BaseURL + if Config.DisplayURL == "" { + Config.DisplayURL = Config.BaseURL + } + return Config } diff --git a/web/src/Home/Home.js b/web/src/Home/Home.js index 23562c3..51db5e4 100644 --- a/web/src/Home/Home.js +++ b/web/src/Home/Home.js @@ -18,7 +18,8 @@ export default class HomeComponent extends Component { usedSettings: this.urlParams.get('customUrl') ? ['custom'] : [], customID: this.urlParams.get('customUrl') ? this.urlParams.get('customUrl') : '', showCustomIDError: false, - expiration: null + expiration: null, + displayURL: window.location.origin } } handleURLChange = (e, { value }) => this.url = value @@ -31,12 +32,13 @@ export default class HomeComponent extends Component { onSettingsChange = (e, { value }) => { this.setState({ usedSettings: value }) } - - - + componentDidMount() { this.urlInput.focus() + fetch("/displayurl") + .then(response => response.json()) + .then(data => this.setState({displayURL: data})); } handleURLSubmit = () => { if (!this.state.showCustomIDError) { @@ -47,7 +49,7 @@ export default class HomeComponent extends Component { Password: this.state.usedSettings.includes("protected") && this.password ? this.password : undefined }, r => this.setState({ links: [...this.state.links, { - shortenedURL: r.URL, + shortenedURL: this.state.displayURL + "/" + this.state.customID, originalURL: this.url, expiration: this.state.usedSettings.includes("expire") && this.state.expiration ? this.state.expiration.toISOString() : undefined, deletionURL: r.DeletionURL @@ -89,7 +91,7 @@ export default class HomeComponent extends Component { {usedSettings.includes("custom") && - + } diff --git a/web/src/Lookup/Lookup.js b/web/src/Lookup/Lookup.js index 00620f2..218aeb3 100644 --- a/web/src/Lookup/Lookup.js +++ b/web/src/Lookup/Lookup.js @@ -6,15 +6,21 @@ import CustomCard from '../Card/Card' export default class LookupComponent extends Component { state = { - links: [] + links: [], + displayURL: window.location.origin + } + componentDidMount() { + fetch("/displayurl") + .then(response => response.json()) + .then(data => this.setState({displayURL: data})); } handleURLChange = (e, { value }) => this.url = value handleURLSubmit = () => { - let id = this.url.replace(window.location.origin + "/", "") + let id = this.url.replace(this.state.displayURL + "/", "") util.lookupEntry(id, res => this.setState({ links: [...this.state.links, [ res.URL, - this.url, + this.state.displayURL + "/" + this.url, this.VisitCount, res.CratedOn, res.LastVisit, @@ -30,7 +36,7 @@ export default class LookupComponent extends Component {
URL Lookup
- this.urlInput = input} action={{ icon: 'arrow right', labelPosition: 'right', content: 'Lookup' }} type='url' onChange={this.handleURLChange} name='url' placeholder={window.location.origin + "/..."} autoComplete="off" /> + this.urlInput = input} action={{ icon: 'arrow right', labelPosition: 'right', content: 'Lookup' }} type='text' label={this.state.displayURL + "/"} onChange={this.handleURLChange} name='url' placeholder={"short url"} autoComplete="off" />
diff --git a/web/src/Recent/Recent.js b/web/src/Recent/Recent.js index 6ab2ad3..396c767 100644 --- a/web/src/Recent/Recent.js +++ b/web/src/Recent/Recent.js @@ -8,11 +8,15 @@ import util from '../util/util' export default class RecentComponent extends Component { state = { - recent: [] + recent: [], + displayURL: window.location.origin } componentDidMount() { this.loadRecentURLs() + fetch("/displayurl") + .then(response => response.json()) + .then(data => this.setState({displayURL: data})); } loadRecentURLs = () => { @@ -47,7 +51,7 @@ export default class RecentComponent extends Component { }, { Header: 'Short URL', accessor: "ID", - Cell: props => `${window.location.origin}/${props.value}` + Cell: props => `${this.state.displayURL}/${props.value}` }, { Header: 'Visitor count', accessor: "Public.VisitCount"