Skip to content

Commit

Permalink
Move /shorten to /api/shorten_url (elastic#21808)
Browse files Browse the repository at this point in the history
* Move /shorten to /api/shorten_url

* better API test assertions

* add API documenation

* use async await

* import dependencies instead of pass in
  • Loading branch information
nreese committed Aug 9, 2018
1 parent d32a652 commit 803a3f1
Show file tree
Hide file tree
Showing 21 changed files with 426 additions and 215 deletions.
2 changes: 2 additions & 0 deletions docs/api.asciidoc
Expand Up @@ -29,8 +29,10 @@ entirely.

* <<saved-objects-api>>
* <<logstash-configuration-management-api>>
* <<url-shortening-api>>
--

include::api/saved-objects.asciidoc[]
include::api/logstash-configuration-management.asciidoc[]
include::api/url-shortening.asciidoc[]

11 changes: 11 additions & 0 deletions docs/api/url-shortening.asciidoc
@@ -0,0 +1,11 @@
[[url-shortening-api]]
== URL Shortening API

Kibana URLs contain the state of the application making them very long and cumbersome.
Internet Explorer has URL length restrictions, and some wiki and markup parsers don't do well with the full-length version of the Kibana URL.

The short URLs enabled by this API are designed to make sharing Kibana URLs easier.

* <<url-shortening-api-api-shorten-url>>

include::url_shortening/shorten_url.asciidoc[]
46 changes: 46 additions & 0 deletions docs/api/url_shortening/shorten_url.asciidoc
@@ -0,0 +1,46 @@
[[url-shortening-api-api-shorten-url]]
=== Shorten URL

The Shorten URL API allows for converting a Kibana URL into a token.

==== Request

`POST /api/shorten_url`

==== Request Body

The request body must be a JSON object containing the following properties:

`url` (required)::
(string) Kibana URL, relative to `/app/kibana`, to be shortened.

==== Response body

The response body will have a top level `urlId` property that contains
the shortened URL token for the provided request body.

==== Examples


[source,js]
--------------------------------------------------
POST api/shorten_url
{
"url": "/app/kibana#/dashboard?_g=()&_a=(description:'',filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(),gridData:(h:15,i:'1',w:24,x:0,y:0),id:'8f4d0c00-4c86-11e8-b3d7-01146121b73d',panelIndex:'1',type:visualization,version:'7.0.0-alpha1')),query:(language:lucene,query:''),timeRestore:!f,title:'New%20Dashboard',viewMode:edit)",
}
--------------------------------------------------
// KIBANA

A successful call returns a response code of `200` and a response body
containing a JSON structure similar to the following example:

[source,js]
--------------------------------------------------
{
"urlId": "f73b295ff92718b26bc94edac766d8e3"
}
--------------------------------------------------

A shortened Kibana URL can then be constructed for easier sharing.
`http://localhost:5601/goto/f73b295ff92718b26bc94edac766d8e3`

44 changes: 0 additions & 44 deletions src/server/http/index.js
Expand Up @@ -23,18 +23,13 @@ import _ from 'lodash';
import Boom from 'boom';
import Hapi from 'hapi';
import { setupVersionCheck } from './version_check';
import { handleShortUrlError } from './short_url_error';
import { shortUrlAssertValid } from './short_url_assert_valid';
import { shortUrlLookupProvider } from './short_url_lookup';
import { registerHapiPlugins } from './register_hapi_plugins';
import { setupXsrf } from './xsrf';

export default async function (kbnServer, server, config) {
kbnServer.server = new Hapi.Server();
server = kbnServer.server;

const shortUrlLookup = shortUrlLookupProvider(server);

// Note that all connection options configured here should be exactly the same
// as in `getServerOptions()` in the new platform (see `src/core/server/http/http_tools`).
//
Expand Down Expand Up @@ -142,45 +137,6 @@ export default async function (kbnServer, server, config) {
}
});

server.route({
method: 'GET',
path: '/goto/{urlId}',
handler: async function (request, reply) {
try {
const url = await shortUrlLookup.getUrl(request.params.urlId, request);
shortUrlAssertValid(url);

const uiSettings = request.getUiSettingsService();
const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage');
if (!stateStoreInSessionStorage) {
reply().redirect(config.get('server.basePath') + url);
return;
}

const app = server.getHiddenUiAppById('stateSessionStorageRedirect');
reply.renderApp(app, {
redirectUrl: url,
});
} catch (err) {
reply(handleShortUrlError(err));
}
}
});

server.route({
method: 'POST',
path: '/shorten',
handler: async function (request, reply) {
try {
shortUrlAssertValid(request.payload.url);
const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request);
reply(urlId);
} catch (err) {
reply(handleShortUrlError(err));
}
}
});

// Expose static assets (fonts, favicons).
server.exposeStaticDir('/ui/fonts/{path*}', resolve(__dirname, '../../ui/public/assets/fonts'));
server.exposeStaticDir('/ui/favicons/{path*}', resolve(__dirname, '../../ui/public/assets/favicons'));
Expand Down
4 changes: 4 additions & 0 deletions src/server/kbn_server.js
Expand Up @@ -36,6 +36,7 @@ import * as Plugins from './plugins';
import { indexPatternsMixin } from './index_patterns';
import { savedObjectsMixin } from './saved_objects';
import { sampleDataMixin } from './sample_data';
import { urlShorteningMixin } from './url_shortening';
import { kibanaIndexMappingsMixin } from './mappings';
import { serverExtensionsMixin } from './server_extensions';
import { uiMixin } from '../ui';
Expand Down Expand Up @@ -93,6 +94,9 @@ export default class KbnServer {
// setup routes for installing/uninstalling sample data sets
sampleDataMixin,

// setup routes for short urls
urlShorteningMixin,

// ensure that all bundles are built, or that the
// watch bundle server is running
optimizeMixin,
Expand Down
20 changes: 20 additions & 0 deletions src/server/url_shortening/index.js
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export { urlShorteningMixin } from './url_shortening_mixin';
50 changes: 50 additions & 0 deletions src/server/url_shortening/routes/create_routes.js
@@ -0,0 +1,50 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { handleShortUrlError } from './lib/short_url_error';
import { shortUrlAssertValid } from './lib/short_url_assert_valid';
import { shortUrlLookupProvider } from './lib/short_url_lookup';
import { createGotoRoute } from './goto';
import { createShortenUrlRoute } from './shorten_url';


export function createRoutes(server, config) {
const shortUrlLookup = shortUrlLookupProvider(server);

server.route(createGotoRoute({ server, config, shortUrlLookup }));
server.route(createShortenUrlRoute({ shortUrlLookup }));

// TODO remove deprecated '/shorten' API in master (7.0)
server.route({
method: 'POST',
path: '/shorten',
handler: async function (request, reply) {
server.log(
['warning', 'deprecation'],
`'/shorten' API has been deprecated and will be removed in 7.0, use the '/api/shorten_url' API instead`);
try {
shortUrlAssertValid(request.payload.url);
const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request);
reply(urlId);
} catch (err) {
reply(handleShortUrlError(err));
}
}
});
}
46 changes: 46 additions & 0 deletions src/server/url_shortening/routes/goto.js
@@ -0,0 +1,46 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { handleShortUrlError } from './lib/short_url_error';
import { shortUrlAssertValid } from './lib/short_url_assert_valid';

export const createGotoRoute = ({ server, config, shortUrlLookup }) => ({
method: 'GET',
path: '/goto/{urlId}',
handler: async function (request, reply) {
try {
const url = await shortUrlLookup.getUrl(request.params.urlId, request);
shortUrlAssertValid(url);

const uiSettings = request.getUiSettingsService();
const stateStoreInSessionStorage = await uiSettings.get('state:storeInSessionStorage');
if (!stateStoreInSessionStorage) {
reply().redirect(config.get('server.basePath') + url);
return;
}

const app = server.getHiddenUiAppById('stateSessionStorageRedirect');
reply.renderApp(app, {
redirectUrl: url,
});
} catch (err) {
reply(handleShortUrlError(err));
}
}
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Expand Up @@ -19,7 +19,7 @@

import sinon from 'sinon';
import { shortUrlLookupProvider } from './short_url_lookup';
import { SavedObjectsClient } from '../saved_objects';
import { SavedObjectsClient } from '../../../saved_objects';

describe('shortUrlLookupProvider', () => {
const ID = 'bf00ad16941fc51420f91a93428b27a0';
Expand Down
35 changes: 35 additions & 0 deletions src/server/url_shortening/routes/shorten_url.js
@@ -0,0 +1,35 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { handleShortUrlError } from './lib/short_url_error';
import { shortUrlAssertValid } from './lib/short_url_assert_valid';

export const createShortenUrlRoute = ({ shortUrlLookup }) => ({
method: 'POST',
path: '/api/shorten_url',
handler: async function (request, reply) {
try {
shortUrlAssertValid(request.payload.url);
const urlId = await shortUrlLookup.generateUrlId(request.payload.url, request);
reply({ urlId });
} catch (err) {
reply(handleShortUrlError(err));
}
}
});
23 changes: 23 additions & 0 deletions src/server/url_shortening/url_shortening_mixin.js
@@ -0,0 +1,23 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { createRoutes } from './routes/create_routes';

export function urlShorteningMixin(kbnServer, server, config) {
createRoutes(server, config);
}

0 comments on commit 803a3f1

Please sign in to comment.