1
0
mirror of https://github.com/cydrobolt/polr.git synced 2024-11-09 11:42:28 +01:00

Bulk link creation API (#443)

* Add bulk shortening API endpoint & create controller methods
* Update documentation
* Remove space %20 mapping for bulk API
This commit is contained in:
Chaoyi Zha 2018-04-20 21:35:45 -04:00 committed by GitHub
parent b29c5d51a9
commit 1fb607ba63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 141 additions and 28 deletions

View File

@ -66,13 +66,13 @@ class LinkFactory {
// has custom ending // has custom ending
$ending_conforms = LinkHelper::validateEnding($custom_ending); $ending_conforms = LinkHelper::validateEnding($custom_ending);
if (!$ending_conforms) { if (!$ending_conforms) {
throw new \Exception('Sorry, but custom endings throw new \Exception('Custom endings
can only contain alphanumeric characters, hyphens, and underscores.'); can only contain alphanumeric characters, hyphens, and underscores.');
} }
$ending_in_use = LinkHelper::linkExists($custom_ending); $ending_in_use = LinkHelper::linkExists($custom_ending);
if ($ending_in_use) { if ($ending_in_use) {
throw new \Exception('Sorry, but this URL ending is already in use.'); throw new \Exception('This URL ending is already in use.');
} }
$link_ending = $custom_ending; $link_ending = $custom_ending;
@ -97,7 +97,6 @@ class LinkFactory {
$link->is_api = $is_api; $link->is_api = $is_api;
if ($creator) { if ($creator) {
// if user is logged in, save user as creator
$link->creator = $creator; $link->creator = $creator;
} }

View File

@ -7,12 +7,22 @@ use App\Helpers\LinkHelper;
use App\Exceptions\Api\ApiException; use App\Exceptions\Api\ApiException;
class ApiLinkController extends ApiController { class ApiLinkController extends ApiController {
protected function getShortenedLink($long_url, $is_secret, $custom_ending, $link_ip, $username, $response_type) {
try {
$formatted_link = LinkFactory::createLink(
$long_url, $is_secret, $custom_ending, $link_ip, $username, false, true);
}
catch (\Exception $e) {
throw new ApiException('CREATION_ERROR', $e->getMessage(), 400, $response_type);
}
return $formatted_link;
}
public function shortenLink(Request $request) { public function shortenLink(Request $request) {
$response_type = $request->input('response_type'); $response_type = $request->input('response_type');
$user = $request->user; $user = $request->user;
// Validate parameters
// Encode spaces as %20 to avoid validator conflicts
$validator = \Validator::make(array_merge([ $validator = \Validator::make(array_merge([
'url' => str_replace(' ', '%20', $request->input('url')) 'url' => str_replace(' ', '%20', $request->input('url'))
], $request->except('url')), [ ], $request->except('url')), [
@ -23,22 +33,71 @@ class ApiLinkController extends ApiController {
throw new ApiException('MISSING_PARAMETERS', 'Invalid or missing parameters.', 400, $response_type); throw new ApiException('MISSING_PARAMETERS', 'Invalid or missing parameters.', 400, $response_type);
} }
$long_url = $request->input('url'); // * required $formatted_link = $this->getShortenedLink(
$is_secret = ($request->input('is_secret') == 'true' ? true : false); $request->input('url'),
($request->input('is_secret') == 'true' ? true : false),
$link_ip = $request->ip(); $request->input('custom_ending'),
$custom_ending = $request->input('custom_ending'); $request->ip(),
$user->username,
try { $response_type
$formatted_link = LinkFactory::createLink($long_url, $is_secret, $custom_ending, $link_ip, $user->username, false, true); );
}
catch (\Exception $e) {
throw new ApiException('CREATION_ERROR', $e->getMessage(), 400, $response_type);
}
return self::encodeResponse($formatted_link, 'shorten', $response_type); return self::encodeResponse($formatted_link, 'shorten', $response_type);
} }
public function shortenLinksBulk(Request $request) {
$response_type = $request->input('response_type', 'json');
$request_data = $request->input('data');
$user = $request->user;
$link_ip = $request->ip();
$username = $user->username;
if ($response_type != 'json') {
throw new ApiException('JSON_ONLY', 'Only JSON-encoded responses are available for this endpoint.', 401, $response_type);
}
$links_array_raw_json = json_decode($request_data, true);
if ($links_array_raw_json === null) {
throw new ApiException('INVALID_PARAMETERS', 'Invalid JSON.', 400, $response_type);
}
$links_array = $links_array_raw_json['links'];
foreach ($links_array as $link) {
$validator = \Validator::make($link, [
'url' => 'required|url'
]);
if ($validator->fails()) {
throw new ApiException('MISSING_PARAMETERS', 'Invalid or missing parameters.', 400, $response_type);
}
}
$formatted_links = [];
foreach ($links_array as $link) {
$formatted_link = $this->getShortenedLink(
$link['url'],
(array_get($link, 'is_secret') == 'true' ? true : false),
array_get($link, 'custom_ending'),
$link_ip,
$username,
$response_type
);
$formatted_links[] = [
'long_url' => $link['url'],
'short_url' => $formatted_link
];
}
return self::encodeResponse([
'shortened_links' => $formatted_links
], 'shorten_bulk', 'json');
}
public function lookupLink(Request $request) { public function lookupLink(Request $request) {
$user = $request->user; $user = $request->user;
$response_type = $request->input('response_type'); $response_type = $request->input('response_type');

View File

@ -66,6 +66,7 @@ $app->group(['prefix' => '/api/v2', 'namespace' => 'App\Http\Controllers\Api', '
/* API shorten endpoints */ /* API shorten endpoints */
$app->post('action/shorten', ['as' => 'api_shorten_url', 'uses' => 'ApiLinkController@shortenLink']); $app->post('action/shorten', ['as' => 'api_shorten_url', 'uses' => 'ApiLinkController@shortenLink']);
$app->get('action/shorten', ['as' => 'api_shorten_url', 'uses' => 'ApiLinkController@shortenLink']); $app->get('action/shorten', ['as' => 'api_shorten_url', 'uses' => 'ApiLinkController@shortenLink']);
$app->post('action/shorten_bulk', ['as' => 'api_shorten_url_bulk', 'uses' => 'ApiLinkController@shortenLinksBulk']);
/* API lookup endpoints */ /* API lookup endpoints */
$app->post('action/lookup', ['as' => 'api_lookup_url', 'uses' => 'ApiLinkController@lookupLink']); $app->post('action/lookup', ['as' => 'api_lookup_url', 'uses' => 'ApiLinkController@lookupLink']);

View File

@ -2,8 +2,8 @@
----------------------------- -----------------------------
## API keys ## API keys
To authenticate a user to Polr, you will need to provide an API key along with To authenticate a user to Polr, you *must* provide an API key along with
each request to the Polr API, as a GET or POST parameter. (e.g `?key=API_KEY_HERE`) each request to Polr API endpoints, as a GET or POST parameter. (e.g `?key=API_KEY_HERE`)
## Assigning an API key ## Assigning an API key
To assign an API key, log on from an administrator account, head over to the "Admin" To assign an API key, log on from an administrator account, head over to the "Admin"
@ -26,11 +26,9 @@ See [API endpoints](#api-endpoints) for more information on the actions.
## Response Type ## Response Type
The Polr API will reply in `plain_text` or `json`. The response type can be The Polr API will reply in `plain_text` or `json`. The response type can be
set by providing the `response_type` argument to the request. If not provided, set by providing the `response_type` argument to the request. If this argument is not provided,
the response type will default to `plain_text`. the response type will default to either `plain_text` or `json` depending
on the endpoint.
Data endpoints will only return JSON-formatted data and will default to `json` if no
`response_type` is provided.
Example `json` responses: Example `json` responses:
``` ```
@ -84,7 +82,61 @@ Response:
} }
``` ```
Remember that the `url` argument must be URL encoded. The `url` argument must be URL encoded.
### /api/v2/action/shorten_bulk
_`POST` only_
Arguments:
- `data`: a string containing a JSON-encoded object with an array of links
Example `data` argument:
```json
{
"links": [
{
"url": "https://polrproject.org/"
},
{
"url": "https://youtube.com",
"is_secret": true
},
{
"url": "https://github.com/cydrobolt/polr",
"custom_ending": "polrgithub"
}
]
}
```
Response: A JSON-encoded object with a list of shortened links.
Example response:
```
{
"action": "shorten_bulk",
"result": {
"shortened_links": [
{
"long_url": "https://polrproject.org/",
"short_url": "http://demo.polr.me/81"
},
{
"long_url": "https://youtube.com",
"short_url": "http://demo.polr.me/84/b496"
},
{
"long_url": "https://github.com/cydrobolt/polr",
"short_url": "http://demo.polr.me/polrgithub"
}
]
}
}
```
### /api/v2/action/lookup ### /api/v2/action/lookup
The `lookup` action takes a single argument: `url_ending`. This is the URL to The `lookup` action takes a single argument: `url_ending`. This is the URL to

View File

@ -8,6 +8,8 @@ it to `true` in `.env`
`MISSING_PARAMETERS`: Invalid or missing parameters. `MISSING_PARAMETERS`: Invalid or missing parameters.
`INVALID_PARAMETERS`: Invalid parameters.
`NOT_FOUND`: Object not found. `NOT_FOUND`: Object not found.
`ACCESS_DENIED`: User is not authorized to access the object. `ACCESS_DENIED`: User is not authorized to access the object.

View File

@ -23,7 +23,7 @@ you may be interested in looking at a [legacy 1.x release](https://github.com/cy
- JSON PHP Extension - JSON PHP Extension
- PHP curl extension - PHP curl extension
## Downloading the source code ## Download the source code
If you would like to download a stable version of Polr, you may check out [the releases page](https://github.com/cydrobolt/polr/releases). If you would like to download a stable version of Polr, you may check out [the releases page](https://github.com/cydrobolt/polr/releases).
@ -49,7 +49,7 @@ $ chown -R apache polr
$ chcon -R -t httpd_sys_rw_content_t polr/storage polr/.env $ chcon -R -t httpd_sys_rw_content_t polr/storage polr/.env
``` ```
## Installing using `composer` ## Install `composer` dependencies
```bash ```bash
# download composer package # download composer package
@ -177,7 +177,7 @@ server {
To run Polr on another HTTP server or on shared hosting, you will need to set the home To run Polr on another HTTP server or on shared hosting, you will need to set the home
directory to `/PATH_TO_POLR/public`, not the root Polr folder. directory to `/PATH_TO_POLR/public`, not the root Polr folder.
## Creating the database ## Create the database
### MySQL ### MySQL