⌈⌋ ⎇ branch:  freshcode


Update of "API2"

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview

Artifact ID: 9d06251a9ac5fe0065aea517e8977f6f97fb1d5f
Page Name:API2
Date: 2015-04-13 19:27:12
Original User: mario
Mimetype:text/x-markdown
Parent: 1b389a8ef3cddebaf68ba9c328010c9ee8ff448d (diff)
Next d0dcaa620b2a65446775b8a3df636389b19f8e8d
Content

State: design, testing

Simpler JSON API

To update and submit project records, there's going to be a simplified JSON interface. Both JSON object keys and URLs are up for discussion.

URL scheme

Updating and release publishing can now be combined into one PUT request. The URL dict can now be embedded even. And DELETE works with just the version string now, no arbitrary numeric <id>.

method URL path function state
GET /projects/<name>.json query kept
PUT /projects/<name>.json update_core combined
CREATE /projects/<name>.json new_project new
POST /projects/<name>/releases.json publish redundant
DELETE /projects/<name>/releases/<verstr>.json?auth_code= withdraw simpler
PUSH /projects/<name>/urls.json update_urls redundant
GET /feed/<name>.json release_list external

The POST .../releases.json and PUSH .../urls.json methods could really be dropped.

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>

method 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> .netrc -
- social_links - - -
- autoupdate_* - - -
DELETE name name -P name -
DELETE deleted - -d -
PENDING t_published created_at -q -d -
PENDING t_changed approved_at -q -d -

Renamed:

  • "permalink" is now just "name"
  • "changelog" became just "changes" now

New:

  • "title"
  • "summary"
  • "urls" as dict {…}, no more "approved_urls"
  • "submitter" for Author name, optional@email

Changes:

  • "project_tag_list" is now just a CSV text field, not JSON [ ] wrapped
  • same as "license_list" is now CSV, accepts "bsd,mitl" or "SPACE, LICENSE"

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. Primarily this is used with the DELETE method. The GET method only hides a few internal fields when unauthorized.

POST/PUT/etc. requests instead should contain the password wrapped in the JSON payload outermost:

{
    "auth_code": "plain_pw_123",
    "project": {
        "key": "Value",
        ...
    }
}

Query GET /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",
        "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"
    }
}

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 PUT /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 Examplary, 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 GET/PUSH /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/",
        "image": "http://launchpad.com/proj/screenshot.png",
    }
}

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.

Release publishing POST /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.",
        "hidden": true,
    }
}

Note that even the "hidden" field is already available with regular project PUT / core updates.

Withdraw_release DELETE /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.

DELETE /projects/<name>/1.2.3-rc2.json?auth_code=pw123 HTTP/1.1

The version string needs to be URL-encoded as needed of course.

New_project CREATE /projects/<name>.json

The JSON payload for creating a new project listing is also practically identical to the regular PUT update.

{
    "auth_code": "this:is-a/brand#new+password_567",
    "project": {
        "title": "Initial Title",
        "author": "Username, user@localhost",
        "summary": "ONELINER",
        "description": "Description REQUIRED.",
        "image": null,
        "license": null,
        "project_tags": "bash, script",
        "author": null,
        "urls": {
            "homepage": "http://example.org/",
        },
        "version": null,
    }
}

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.

It can however also just be completed with the next PUT Update-core. The only requirements for CREATE are a new Unix project <name> (taken from the request URL), and a "title" and "description", "license" or "tag_list".

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.

SSL Spamguard: Undecided / Testing. See /doc/trunk/doc/submit.pem