Wiki page
[API2] by
mario
2015-04-14 12:09:58.
D 2015-04-14T12:09:58.167
L API2
N text/x-markdown
P 4bc81535936ea89dc2449b0618b2bad59658c8c9
U mario
W 13490
State: ***design***, *testing*
## Simpler JSON API
To update and submit project records, there's going to be a simplified
JSON interface.
* The testing API endpoint is <kbd>`https://test.freshcode.club/…`</kbd>,
which can be used for browsing as well.
* The regular API endpoint is <kbd>`https://api.freshcode.club/…`</kbd>,
but is *currently* fixated on the test database too.
## URL scheme
Updating and release publishing can now be combined into one PUT/POST
request. The URL dict can now be embedded everywhere or passed alongside.
method | URL path |function+purpose
--------------------------------------------------------------------------------
GET |`/projects/<name>.json` |query all fields
PUT |`/projects/<name>.json` |update_core+release
CREATE |`/projects/<name>.json` |new_project+update
<s>POST |<s>`/projects/<name>/releases.json`</s> |<s>publish</s>
DELETE |`/projects/<name>/releases/<verstr>.json`*?auth_code=* |withdraw version
<s>PUSH |<s>`/projects/<name>/urls.json`</s> |<s>update_urls</s>
GET |`/feed/<name>.json` |release_list+federation
The <kbd>PUT</kbd> method likewise works with <kbd>POST</kbd> or
<kbd>PUSH</kbd> ("PUSH" because it's a programming site, and entries are
a stack). Fields are equivalent for the initializing <kbd>CREATE</kbd>.
## JSON object keys
Where the JSON field names are mapped as follows:
<style>
.content table { width: 95%; }
.content table tr td:nth-child(5) { color: #99c; font-style: italic; }
.content table tr td:nth-child(3) { font-weight: bold; color: #272; }
.content table tr td:nth-child(1) { color: #bbb; font-weight: bold; }
</style>
works with | freshcode DB | JSON field | freecode-submit | Sample
------------------------------------------------------------------------------------------
CREATE | name | `<name>` | Project | unix-name
PUT | title | title | Project | Foo Bar Gtk+
PUT | summary | summary | Summary | short slogan
PUT | description | description | Description | Long text...
PUT | tags |`project_tag_list`:| Project-Tag-List | c, c++, cli
PUT | license | `license_list`: | License-List | MITL, GNU GPL
PUT, URL | homepage | urls {…} | Homepage-URL | http://exmpl
PUT, URL | homepage | urls {…} | Website-URL | http://exmpl
PUT, URL | image: | urls {…} | Screenshot-URL | http://png
PUT, URL | autoupdate_url | urls {…} | Changelog-URL | .../NEWS.md
PUT, URL | urls {…} | urls {…} | *******-URL | Title = http://...
RELEASE | download | download | Download-URL | http://sf.net
RELEASE | version | version | Version | 1.0.3-rc5
RELEASE | changes | changes | Changes | Added Xy. Fixed Zy.
RELEASE | hidden |`hidden_from_fp`:| Hide | 0
RELEASE | state |`release_tag_list`:| Release-Tag-List | stable
RELEASE | scope |`release_tag_list`:| Release-Tag-List | minor, bugfix
CREATE | submitter | author | Author | Bob
CREATE | submitter_img | - | Author | Bob, bob@gitub
- | editor_note | - | - | -
- | flag | - | - | -
CREATE | lock | `<auth_code>` | <kbd>.netrc</kbd>| -
- | social_links | - | - | -
- | autoupdate_* | - | - | -
DELETE | name | name | -P name | -
DELETE | deleted | - | -d | -
<s>PENDING</s>| t_published | created_at | -q -d | -
<s>PENDING</s>| t_changed | approved_at | -q -d | -
- Renamed: `permalink` → `name`, and `changelog` → `changes`
- New: `title`, `summary` (oneliner), `urls` as dict {…}, `author` for `submitter`
- Changes: `project_tag_list` now CSV text instead of JSON list, same for
`license_list` with spacing irrelevant
- Internal / Unassigned yet: `editor_note`, `flag`, `lock`, `social_links`,
`autoupdate_***`
### Authorization:
All requests can append an `?auth_code=` to request URLs to carry a plain password.
Which is primarily used with the <kbd>DELETE</kbd> method. The <kbd>GET</kbd> method
only hides a few internal fields when unauthorized.
<kbd>POST</kbd>/<kbd>PUT</kbd>/etc. requests instead should wrap the
password outermost in the JSON payloadt:
{
"auth_code": "plain_pw_123",
"project": {
"key": "Value",
...
}
}
## Query <kbd>GET</kbd> `/projects/<name>.json`
Returns an almost literal database dump:
{
"project": {
"name": "foo-bar",
"title": "Foo Bar",
"summary": "iCal-compatible calendaring app",
"description": "Here comes a very long description ...",
"image": "",
"author": "Bob",
"license_list": "MITL, CC-BY-SA",
"project_tags": "desktop, c++, qt5, calendar",
"homepage": "http://example.org",
"download": "http://example.org/dwnld/",
"urls": {
"homepage": "http://example.org",
"changelog": "https://example.org/downl/NEWS.md",
"DEB": "http://example.org/downl/foo-bar_1.deb",
"download": "http://example.org/dwnld/"
},
"version": "5.0.1",
"state": "stable",
"scope": "minor feature",
"changes": "Fixed the thing, and added the stuff.",
"download": "http://example.org/dwnld/",
"t_published": "1427461501"
},
"$feed-origin": "http://freshcode.club/",
"$feed-license": "CC-BY-SA 3.0"
}
The release fields (second half in the example) represent the latest
known version.
* The URLs are partly duplicated. Because "homepage" and "download" are
core fields, they show up in two places.
* This GET response blob might carry a few more internal fields (autoupdate_*,
lock, t_published, flag, editor_note) if an `?auth_code=` was supplied.
## Update core+release <kbd>PUT</kbd> `/projects/<name>.json`
For changing general project information, all fields can be sent wrapped
in the same structure. The only difference is the required `auth_code`.
{
"auth_code": "plain_pw_123",
"project": {
"title": "New Title",
"summary": "Shorter project slogan",
"description": "New and longer description...",
"image": "http://new.png",
"license_list": "BSDL",
"project_tags": "qt6, dlang, desktop, calendar",
"author": "Elise Exemplary, dj_ical@launchpad",
"urls": {
"homepage": "http://google-code.com",
"DEB": "http://example.org/SECOND-REALEASE.deb",
"download": "http://example.org/dwnld/"
},
"version": "6.0.2",
"state": "stable",
"scope": "minor bugfix",
"changes": "Fixed the thing, and added the stuff.",
"download": "http://example.org/dwnld/",
}
}
Now interestingly, this scheme can be used to:
1. Just update the basic project description.
2. Or publish new release "version" and "changes" right along.
Either, or, and both.
#### Sectioned variant
As variation of that, the JSON struct ***may*** be split into:
{
"auth_code": "plain_pw_123",
"project": {
"title": "New Title",
"summary": "Shorter project slogan",
"description": "New and longer description...",
"image": "http://new.png",
"license_tags": "BSDL",
"project_tags": "qt6, dlang, desktop, calendar",
"urls": {
"homepage": "http://google-code.com",
"DEB": "http://example.org/SECOND-REALEASE.deb",
"download": "http://example.org/dwnld/"
}
},
"release": {
"version": "6.0.2",
"state": "stable",
"scope": "minor bugfix",
"changes": "Fixed the thing, and added the stuff.",
"download": "http://example.org/dwnld/",
"hide": false,
}
}
It'll simply be rejoined server-side. Which doesn't make a difference
to the internal database scheme. Might be more convenient to implement.
#### URL section moved out
And as further variation, you can also split out the `url:{}` dict:
{
"auth_code": "plain_pw_123",
"project": {
"title": "New Title",
"description": "................"
"editor_note": "Please reset the social bookmark counter!
Project moved from Sourceforge to GitHub."
},
"urls": {
"homepage": "http://example.org/",
"proprietary-hoster": "http://github.com/proj/name/",
"PYZ-package": "http://example.org/calendar.pyzw",
}
"release": {
"version": "7.5.3",
"changes": "Rome sprang up...",
}
}
The API is pretty much indifferent if this wraps up just the "project"
base information, a lone "urls" dict, or just a "release" or any
combination thereof.
## URLs dict <kbd>GET</kbd>/<kbd>PUSH</kbd> `/projects/<name>/urls.json`
There's still a separate API endpoint for just retrieving or updating
the URLs though:
{
"auth_code": "plain_pw_123",
"urls": {
"Homepage": "http://example.org/",
"screenshot": "http://launchpad.com/proj/screenshot.png",
"Custom-name": "http://example.com/share/help/C/ping/index.page",
}
}
Note that a projects "homepage" or "download" or "image" URL only get
updated when listed herein. All other project links get completely
discarded and replaced by whatever is in the new list.
* Incoming link titles are *free-form*.
* The case is preserved for custom entries.
* Non-word characters are replaced.
* Titles will always be stored with "Dashed-Names" (it's internally
a `Key=Url` text/yaml field).
* The core URLs (homepage, download, screenshot) however are always
lowercased (when returned on GET requests).
* The API is indifferent if you pass the "homepage" or "download"
link as literal `project:{…}` dict entry, or wrapped in `urls:{…}`.
## Release publishing <kbd>POST</kbd> `/projects/<name>/releases.json`
This is entirely redundant now. But a new release can be published
with that alternative URL scheme. It's basically identical to
"PUT `/projec/<name>.json`" now:
{
"auth_code": "plain_pw_123",
"release": {
"version": "0.0.1",
"state": "beta",
"scope": "cleanup",
"changes": "Initial release. No docs or code.",
"hide": true,
}
}
Note that even the "hidden" field is already available with regular
project PUT / core updates.
## Withdraw_release <kbd>DELETE</kbd> `/projects/<name>/<versionstr>.json`
Now release retraction became simpler as well. There are no longer
arbitrary numeric IDs exposed. (They were faked anyway.)
Instead the *literal version number* can now be used to delete
a release entry.
- <kbd>DELETE</kbd> `/projects/<name>/`*1.2.3-rc2*`.json?auth_code=pw123`
The version string has to be URL-encoded as needed of course.
## New_project <kbd>CREATE</kbd> `/projects/<name>.json`
The JSON payload for creating a new project might look familiar.
Well in fact, *it is* identical to the regular PUT payload:
{
"auth_code": "this:is-a/brand#new+password_567",
"project": {
"title": "Initial Title",
"author": "Username, user@localhost",
"summary": "ONELINER",
"description": "Description REQUIRED.",
"screenshot": null,
"license": null,
"project_tags": "bash, script",
"author": null,
"urls": {
"homepage": "http://example.org/",
},
"version": null,
"state": "beta",
"scope": "security bugfix",
"changes": "..."
}
}
The `null` fields are just for brevity. In fact the first project
submission *can and **should** even* contain a full record - including
the current release version/infos. (CREATE cannot be used to register
all-empty or stub project records.)
It can however also just be completed with the next <kbd>PUT</kbd>/Update.
The only requirements for <kbd>CREATE</kbd> are a new Unix project`<name>`
(taken from the request URL), and a "`title`" and "`description`",
"`license`" or "`tag_list`", and a "`homepage`" URL.
And obviously this is the only time the ‹`auth_code`› is used for
populating the internal authorization hash. All other requests just
compare it, but CREATE does the creative step.
Client SSL cert as CREATE spamguard: **Undecided** / *Testing*.
See also [/doc/trunk/doc/submit.pem](doc/trunk/doc/submit.pem) for public
authorization key.
Z 2b6d30629e0b3cbfe77ecce27e699d30