Merge branch 'fix-time-ago', closes #69
This commit is contained in:
commit
ffd5882810
@ -183,7 +183,8 @@ def make_app(conf=None, threading=True, multiprocessing=False, uwsgi=False):
|
|||||||
'/css': join(dirname(__file__), 'css/')}))
|
'/css': join(dirname(__file__), 'css/')}))
|
||||||
|
|
||||||
wrapper.append(partial(wsgi.CORSMiddleware,
|
wrapper.append(partial(wsgi.CORSMiddleware,
|
||||||
origin=origin(isso.conf.getiter("general", "host"))))
|
origin=origin(isso.conf.getiter("general", "host")),
|
||||||
|
allowed=("Origin", "Content-Type"), exposed=("X-Set-Cookie", "Date")))
|
||||||
|
|
||||||
wrapper.extend([wsgi.SubURI, ProxyFix])
|
wrapper.extend([wsgi.SubURI, ProxyFix])
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
define(["app/lib/promise"], function(Q) {
|
define(["app/lib/promise", "app/globals"], function(Q, globals) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -41,8 +41,9 @@ define(["app/lib/promise"], function(Q) {
|
|||||||
|
|
||||||
function onload() {
|
function onload() {
|
||||||
|
|
||||||
var cookie = xhr.getResponseHeader("X-Set-Cookie");
|
globals.offset.update(new Date(xhr.getResponseHeader("Date")));
|
||||||
|
|
||||||
|
var cookie = xhr.getResponseHeader("X-Set-Cookie");
|
||||||
if (cookie && cookie.match(/^isso-/)) {
|
if (cookie && cookie.match(/^isso-/)) {
|
||||||
document.cookie = cookie;
|
document.cookie = cookie;
|
||||||
}
|
}
|
||||||
|
21
isso/js/app/globals.js
Normal file
21
isso/js/app/globals.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
define(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Offset = function() {
|
||||||
|
this.values = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
Offset.prototype.update = function(remoteTime) {
|
||||||
|
this.values.push((new Date()).getTime() - remoteTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
Offset.prototype.localTime = function() {
|
||||||
|
return new Date((new Date()).getTime() + this.values.reduce(
|
||||||
|
function(a, b) { return a + b; }) / this.values.length);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
offset: new Offset()
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
/* Isso – Ich schrei sonst!
|
/* Isso – Ich schrei sonst!
|
||||||
*/
|
*/
|
||||||
define(["app/text/html", "app/dom", "app/utils", "app/config", "app/api", "app/markup", "app/i18n", "app/lib"],
|
define(["app/text/html", "app/dom", "app/utils", "app/config", "app/api", "app/markup", "app/i18n", "app/lib", "app/globals"],
|
||||||
function(templates, $, utils, config, api, Mark, i18n, lib) {
|
function(templates, $, utils, config, api, Mark, i18n, lib, globals) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ define(["app/text/html", "app/dom", "app/utils", "app/config", "app/api", "app/m
|
|||||||
// update datetime every 60 seconds
|
// update datetime every 60 seconds
|
||||||
var refresh = function() {
|
var refresh = function() {
|
||||||
$(".permalink > date", el).textContent = utils.ago(
|
$(".permalink > date", el).textContent = utils.ago(
|
||||||
new Date(parseInt(comment.created, 10) * 1000));
|
globals.offset.localTime(), new Date(parseInt(comment.created, 10) * 1000));
|
||||||
setTimeout(refresh, 60*1000);
|
setTimeout(refresh, 60*1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@ define(["app/markup"], function(Mark) {
|
|||||||
return (document.cookie.match('(^|; )' + cookie + '=([^;]*)') || 0)[2];
|
return (document.cookie.match('(^|; )' + cookie + '=([^;]*)') || 0)[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
var ago = function(date) {
|
var ago = function(localTime, date) {
|
||||||
|
|
||||||
var diff = (((new Date()).getTime() - date.getTime()) / 1000),
|
var diff = ((localTime.getTime() - date.getTime()) / 1000),
|
||||||
day_diff = Math.floor(diff / 86400);
|
day_diff = Math.floor(diff / 86400);
|
||||||
|
|
||||||
if (isNaN(day_diff) || day_diff < 0) {
|
if (isNaN(day_diff) || day_diff < 0) {
|
||||||
|
14
isso/wsgi.py
14
isso/wsgi.py
@ -60,19 +60,25 @@ class SubURI(object):
|
|||||||
class CORSMiddleware(object):
|
class CORSMiddleware(object):
|
||||||
"""Add Cross-origin resource sharing headers to every request."""
|
"""Add Cross-origin resource sharing headers to every request."""
|
||||||
|
|
||||||
def __init__(self, app, origin):
|
methods = ("HEAD", "GET", "POST", "PUT", "DELETE")
|
||||||
|
|
||||||
|
def __init__(self, app, origin, allowed=[], exposed=[]):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.origin = origin
|
self.origin = origin
|
||||||
|
self.allowed = allowed
|
||||||
|
self.exposed = exposed
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
|
|
||||||
def add_cors_headers(status, headers, exc_info=None):
|
def add_cors_headers(status, headers, exc_info=None):
|
||||||
headers = Headers(headers)
|
headers = Headers(headers)
|
||||||
headers.add("Access-Control-Allow-Origin", self.origin(environ))
|
headers.add("Access-Control-Allow-Origin", self.origin(environ))
|
||||||
headers.add("Access-Control-Allow-Headers", "Origin, Content-Type")
|
|
||||||
headers.add("Access-Control-Allow-Credentials", "true")
|
headers.add("Access-Control-Allow-Credentials", "true")
|
||||||
headers.add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
|
headers.add("Access-Control-Allow-Methods", ", ".join(self.methods))
|
||||||
headers.add("Access-Control-Expose-Headers", "X-Set-Cookie")
|
if self.allowed:
|
||||||
|
headers.add("Access-Control-Allow-Headers", ", ".join(self.allowed))
|
||||||
|
if self.exposed:
|
||||||
|
headers.add("Access-Control-Expose-Headers", ", ".join(self.exposed))
|
||||||
return start_response(status, headers.to_list(), exc_info)
|
return start_response(status, headers.to_list(), exc_info)
|
||||||
|
|
||||||
if environ.get("REQUEST_METHOD") == "OPTIONS":
|
if environ.get("REQUEST_METHOD") == "OPTIONS":
|
||||||
|
@ -22,21 +22,23 @@ class CORSTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
|
|
||||||
app = CORSMiddleware(hello_world, origin=origin([
|
app = CORSMiddleware(hello_world,
|
||||||
"https://example.tld/",
|
origin=origin([
|
||||||
"http://example.tld/",
|
"https://example.tld/",
|
||||||
"http://example.tld",
|
"http://example.tld/",
|
||||||
]))
|
"http://example.tld",
|
||||||
|
]),
|
||||||
|
allowed=("Foo", "Bar"), exposed=("Spam", ))
|
||||||
|
|
||||||
client = Client(app, Response)
|
client = Client(app, Response)
|
||||||
|
|
||||||
rv = client.get("/", headers={"ORIGIN": "https://example.tld"})
|
rv = client.get("/", headers={"ORIGIN": "https://example.tld"})
|
||||||
|
|
||||||
self.assertEqual(rv.headers["Access-Control-Allow-Origin"], "https://example.tld")
|
self.assertEqual(rv.headers["Access-Control-Allow-Origin"], "https://example.tld")
|
||||||
self.assertEqual(rv.headers["Access-Control-Allow-Headers"], "Origin, Content-Type")
|
|
||||||
self.assertEqual(rv.headers["Access-Control-Allow-Credentials"], "true")
|
self.assertEqual(rv.headers["Access-Control-Allow-Credentials"], "true")
|
||||||
self.assertEqual(rv.headers["Access-Control-Allow-Methods"], "GET, POST, PUT, DELETE")
|
self.assertEqual(rv.headers["Access-Control-Allow-Methods"], "HEAD, GET, POST, PUT, DELETE")
|
||||||
self.assertEqual(rv.headers["Access-Control-Expose-Headers"], "X-Set-Cookie")
|
self.assertEqual(rv.headers["Access-Control-Allow-Headers"], "Foo, Bar")
|
||||||
|
self.assertEqual(rv.headers["Access-Control-Expose-Headers"], "Spam")
|
||||||
|
|
||||||
a = client.get("/", headers={"ORIGIN": "http://example.tld"})
|
a = client.get("/", headers={"ORIGIN": "http://example.tld"})
|
||||||
self.assertEqual(a.headers["Access-Control-Allow-Origin"], "http://example.tld")
|
self.assertEqual(a.headers["Access-Control-Allow-Origin"], "http://example.tld")
|
||||||
@ -50,7 +52,8 @@ class CORSTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_preflight(self):
|
def test_preflight(self):
|
||||||
|
|
||||||
app = CORSMiddleware(hello_world, origin=origin(["http://example.tld"]))
|
app = CORSMiddleware(hello_world, origin=origin(["http://example.tld"]),
|
||||||
|
allowed=("Foo", ), exposed=("Bar", ))
|
||||||
client = Client(app, Response)
|
client = Client(app, Response)
|
||||||
|
|
||||||
rv = client.open(method="OPTIONS", path="/", headers={"ORIGIN": "http://example.tld"})
|
rv = client.open(method="OPTIONS", path="/", headers={"ORIGIN": "http://example.tld"})
|
||||||
|
Loading…
Reference in New Issue
Block a user