/comment/ -> /1.0/
This commit is contained in:
parent
ac6d88f61e
commit
39899dda81
32
Readme.md
32
Readme.md
@ -38,33 +38,33 @@ please file in a bug report \*including\* your dump.
|
||||
|
||||
## API
|
||||
|
||||
### fetch comments for /foo-bar/
|
||||
To fetch all comments for a path, run
|
||||
|
||||
$ curl -H "Accept: application/json" http://example.org/comment/foo-bar/
|
||||
|
||||
### comment at /foo-bar/
|
||||
To write a comment, you have to POST a JSON dictionary with the following key-value
|
||||
pairs. Text is mandatory otherwise you'll get a 400 Bad Request. You'll also get
|
||||
a 400 when your JSON is invalid.
|
||||
|
||||
$ curl -H "Accept: application/json" -X POST -d \
|
||||
Let's say you want to comment on /foo-bar/
|
||||
|
||||
$ curl http://example.org/comment/foo-bar/new -H "Accept: application/json" -X POST -d \
|
||||
'{
|
||||
"text": "Lorem ipsum ...",
|
||||
|
||||
# optional
|
||||
"name": "Hans", "email": "foo@bla.org", "website": "http://blog/log/"
|
||||
}' http://example.org/comment/foo-bar/new
|
||||
}'
|
||||
|
||||
### modify 12. comment at /foo-bar/
|
||||
This will set a cookie, that expires in a few minutes (15 minutes per default). This
|
||||
cookie allows you do modify or delete your comment. Don't try to modify that cookie,
|
||||
it is cryptographically signed. If your cookie is outdated or modified, you'll get
|
||||
a 403 Forbidden.
|
||||
|
||||
$ curl -H "Accept: application/json" -X PUT -d ... http://example.org/comment/foo-bar/12
|
||||
For each comment you'll post, you get an unique cookie. Let's try to remove your comment:
|
||||
|
||||
You can only modify your own comment in a given time range (defaults to 15 minutes).
|
||||
$ curl -H ... -X DELETE http://example.org/comment/foo-bar/1
|
||||
|
||||
### delete 2nd comment at /foo-bar/
|
||||
|
||||
$ curl -H ... -X DELETE http://example.org/comment/foo-bar/2
|
||||
|
||||
You can only delete your own comment in a given time range (defaults to 15 minutes). If
|
||||
your comment has been referenced by another comment, your comment will be cleared but not
|
||||
deleted to maintain depending comments.
|
||||
If your comment has been referenced by another comment, your comment will be cleared but
|
||||
not deleted to retain depending comments.
|
||||
|
||||
## Alternatives
|
||||
|
||||
|
@ -55,10 +55,10 @@ url_map = Map([
|
||||
|
||||
# comment API, note that the client side quotes the URL, but this is
|
||||
# actually unnecessary. PEP 333 aka WSGI always unquotes PATH_INFO.
|
||||
url('/comment/<re(".+"):path>/', 'comment.get', ['GET']),
|
||||
url('/comment/<re(".+"):path>/new', 'comment.create', ['POST']),
|
||||
url('/comment/<re(".+"):path>/<int:id>', 'comment.get', ['GET']),
|
||||
url('/comment/<re(".+"):path>/<int:id>', 'comment.modify', ['PUT', 'DELETE']),
|
||||
url('/1.0/<re(".+"):path>/', 'comment.get', ['GET']),
|
||||
url('/1.0/<re(".+"):path>/new', 'comment.create', ['POST']),
|
||||
url('/1.0/<re(".+"):path>/<int:id>', 'comment.get', ['GET']),
|
||||
url('/1.0/<re(".+"):path>/<int:id>', 'comment.modify', ['PUT', 'DELETE']),
|
||||
], converters={'re': RegexConverter})
|
||||
|
||||
|
||||
|
@ -72,7 +72,7 @@ def modify(app, environ, request, path, id):
|
||||
abort(403)
|
||||
|
||||
if not (rv[0] == '*' or rv[0:2] == [path, id]):
|
||||
abort(401)
|
||||
abort(403)
|
||||
|
||||
if request.method == 'PUT':
|
||||
try:
|
||||
|
@ -67,7 +67,7 @@
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/comment/' + encodeURIComponent(window.location.pathname) + '/new',
|
||||
url: '/1.0/' + encodeURIComponent(window.location.pathname) + '/new',
|
||||
method: 'POST',
|
||||
type: 'json',
|
||||
headers: {
|
||||
@ -168,7 +168,7 @@
|
||||
|
||||
$('#isso_' + post['id'] + ' > footer .delete').on('click', function(event) {
|
||||
$.ajax({
|
||||
url: '/comment/' + encodeURIComponent(window.location.pathname) + '/' + post['id'],
|
||||
url: '/1.0/' + encodeURIComponent(window.location.pathname) + '/' + post['id'],
|
||||
method: 'DELETE',
|
||||
error: function(resp) {
|
||||
alert('Mööp!');
|
||||
@ -196,7 +196,7 @@
|
||||
|
||||
var fetch = function(thread) {
|
||||
var rv = $.ajax({
|
||||
url: '/comment/' + encodeURIComponent(window.location.pathname) + '/',
|
||||
url: '/1.0/' + encodeURIComponent(window.location.pathname) + '/',
|
||||
method: 'GET',
|
||||
type: 'json',
|
||||
headers: {
|
||||
|
@ -29,8 +29,8 @@ class TestComments(unittest.TestCase):
|
||||
|
||||
def testGet(self):
|
||||
|
||||
self.post('/comment/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
r = self.get('/comment/path/1')
|
||||
self.post('/1.0/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
r = self.get('/1.0/path/1')
|
||||
assert r.status_code == 200
|
||||
|
||||
rv = json.loads(r.data)
|
||||
@ -40,7 +40,7 @@ class TestComments(unittest.TestCase):
|
||||
|
||||
def testCreate(self):
|
||||
|
||||
rv = self.post('/comment/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
rv = self.post('/1.0/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
|
||||
assert rv.status_code == 201
|
||||
assert len(filter(lambda header: header[0] == 'Set-Cookie', rv.headers)) == 1
|
||||
@ -54,9 +54,9 @@ class TestComments(unittest.TestCase):
|
||||
def testCreateAndGetMultiple(self):
|
||||
|
||||
for i in range(20):
|
||||
self.post('/comment/path/new', data=json.dumps(comment(text='Spam')))
|
||||
self.post('/1.0/path/new', data=json.dumps(comment(text='Spam')))
|
||||
|
||||
r = self.get('/comment/path/')
|
||||
r = self.get('/1.0/path/')
|
||||
assert r.status_code == 200
|
||||
|
||||
rv = json.loads(r.data)
|
||||
@ -64,17 +64,17 @@ class TestComments(unittest.TestCase):
|
||||
|
||||
def testGetInvalid(self):
|
||||
|
||||
assert self.get('/comment/path/123').status_code == 404
|
||||
assert self.get('/comment/path/spam/123').status_code == 404
|
||||
assert self.get('/comment/foo/').status_code == 404
|
||||
assert self.get('/1.0/path/123').status_code == 404
|
||||
assert self.get('/1.0/path/spam/123').status_code == 404
|
||||
assert self.get('/1.0/foo/').status_code == 404
|
||||
|
||||
def testUpdate(self):
|
||||
|
||||
self.post('/comment/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
self.put('/comment/path/1', data=json.dumps(comment(
|
||||
self.post('/1.0/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
self.put('/1.0/path/1', data=json.dumps(comment(
|
||||
text='Hello World', author='me', website='http://example.com/')))
|
||||
|
||||
r = self.get('/comment/path/1')
|
||||
r = self.get('/1.0/path/1')
|
||||
assert r.status_code == 200
|
||||
|
||||
rv = json.loads(r.data)
|
||||
@ -85,45 +85,45 @@ class TestComments(unittest.TestCase):
|
||||
|
||||
def testDelete(self):
|
||||
|
||||
self.post('/comment/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
r = self.delete('/comment/path/1')
|
||||
self.post('/1.0/path/new', data=json.dumps(comment(text='Lorem ipsum ...')))
|
||||
r = self.delete('/1.0/path/1')
|
||||
assert r.status_code == 200
|
||||
assert json.loads(r.data) == None
|
||||
assert self.get('/comment/path/1').status_code == 404
|
||||
assert self.get('/1.0/path/1').status_code == 404
|
||||
|
||||
def testDeleteWithReference(self):
|
||||
|
||||
client = Client(self.app, Response)
|
||||
resp = client.post('/comment/path/new', data=json.dumps(comment(text='First')))
|
||||
self.post('/comment/path/new', data=json.dumps(comment(text='Second', parent=1)))
|
||||
resp = client.post('/1.0/path/new', data=json.dumps(comment(text='First')))
|
||||
self.post('/1.0/path/new', data=json.dumps(comment(text='Second', parent=1)))
|
||||
|
||||
r = client.delete('/comment/path/1')
|
||||
r = client.delete('/1.0/path/1')
|
||||
assert r.status_code == 200
|
||||
assert Comment(**json.loads(r.data)).deleted
|
||||
|
||||
assert self.get('/comment/path/1').status_code == 200
|
||||
assert self.get('/comment/path/2').status_code == 200
|
||||
assert self.get('/1.0/path/1').status_code == 200
|
||||
assert self.get('/1.0/path/2').status_code == 200
|
||||
|
||||
def testPathVariations(self):
|
||||
|
||||
paths = ['/sub/path/', '/path.html', '/sub/path.html', '%2Fpath/%2F']
|
||||
paths = ['/sub/path/', '/path.html', '/sub/path.html', '%2Fpath/%2F', '/']
|
||||
|
||||
for path in paths:
|
||||
assert self.post('/comment/' + path + '/new',
|
||||
assert self.post('/1.0/' + path + '/new',
|
||||
data=json.dumps(comment(text='...'))).status_code == 201
|
||||
|
||||
for path in paths:
|
||||
assert self.get('/comment/' + path)
|
||||
assert self.get('/comment/' + path + '/1')
|
||||
assert self.get('/1.0/' + path)
|
||||
assert self.get('/1.0/' + path + '/1')
|
||||
|
||||
def testDeleteAndCreateByDifferentUsersButSamePostId(self):
|
||||
|
||||
mallory = Client(self.app, Response)
|
||||
mallory.post('/comment/path/new', data=json.dumps(comment(text='Foo')))
|
||||
mallory.delete('/comment/path/1')
|
||||
mallory.post('/1.0/path/new', data=json.dumps(comment(text='Foo')))
|
||||
mallory.delete('/1.0/path/1')
|
||||
|
||||
bob = Client(self.app, Response)
|
||||
bob.post('/comment/path/new', data=json.dumps(comment(text='Bar')))
|
||||
bob.post('/1.0/path/new', data=json.dumps(comment(text='Bar')))
|
||||
|
||||
assert mallory.delete('/comment/path/1').status_code == 403
|
||||
assert bob.delete('/comment/path/1').status_code == 200
|
||||
assert mallory.delete('/1.0/path/1').status_code == 403
|
||||
assert bob.delete('/1.0/path/1').status_code == 200
|
||||
|
Loading…
Reference in New Issue
Block a user