Esempio n. 1
0
def messages_last(request):
    if request.method == 'GET':
        # Get the most recent sent message from the database (empty string by
        #   default), and generate a simple ETag.
        message = LastMessage.get_only().text
        etag = '"%s"' % hashlib.md5(message).hexdigest()

        inm = request.META.get('HTTP_IF_NONE_MATCH')
        wait = (request.GET.get('wait') == 'true')

        if inm == etag:
            # If a matching If-None-Match header was supplied, then return
            #   status 304.
            resp = HttpResponseNotModified()

            if wait:
                # Set the request to hold open as a long-poll, subscribed to
                #   a channel.
                channel = Channel('messages', prev_id=etag)
                set_hold_longpoll(request, channel)
        else:
            resp = HttpResponse(message + '\n',
                content_type='text/plain')

        resp['ETag'] = etag
        return resp
    else:
        return HttpResponseNotAllowed(['GET'])
Esempio n. 2
0
def item(request, headline_id):
    h = get_object_or_404(Headline, pk=headline_id)
    if request.wscontext:
        ws = request.wscontext
        if ws.is_opening():
            ws.accept()
            ws.subscribe('headline-%s' % headline_id)
        while ws.can_recv():
            message = ws.recv()
            if message is None:
                ws.close()
                break
        return HttpResponse()
    elif request.method == 'GET':
        if request.META.get('HTTP_ACCEPT') == 'text/event-stream':
            resp = HttpResponse(content_type='text/event-stream')
            set_hold_stream(resp, 'headline-%s' % headline_id)
            return resp
        else:
            wait = request.META.get('HTTP_WAIT')
            if wait:
                wait = int(wait)
                if wait < 1:
                    wait = None
                if wait > 300:
                    wait = 300
            inm = request.META.get('HTTP_IF_NONE_MATCH')
            etag = '"%s"' % calendar.timegm(h.date.utctimetuple())
            if inm == etag:
                resp = HttpResponseNotModified()
                if wait:
                    set_hold_longpoll(resp, 'headline-%s' % headline_id, timeout=wait)
            else:
                resp = _json_response(h.to_data())
            resp['ETag'] = etag
            return resp
    elif request.method == 'PUT':
        hdata = json.loads(request.read())
        h.type = hdata['type']
        h.title = hdata.get('title', '')
        h.text = hdata.get('text', '')
        h.save()
        hdata = h.to_data()
        hjson = json.dumps(hdata)
        etag = '"%s"' % calendar.timegm(h.date.utctimetuple())
        rheaders = {'ETag': etag}
        hpretty = json.dumps(hdata, indent=4) + '\n'
        formats = list()
        formats.append(HttpResponseFormat(body=hpretty, headers=rheaders))
        formats.append(HttpStreamFormat('event: update\ndata: %s\n\n' % hjson))
        formats.append(WebSocketMessageFormat(hjson))
        publish('headline-%s' % headline_id, formats)
        resp = _json_response(hdata)
        resp['ETag'] = etag
        return resp
    else:
        return HttpResponseNotAllowed(['GET', 'PUT'])
Esempio n. 3
0
def item(request, headline_id):
    h = get_object_or_404(Headline, pk=headline_id)
    if request.wscontext:
        ws = request.wscontext
        if ws.is_opening():
            ws.accept()
            ws.subscribe(headline_id)
        while ws.can_recv():
            message = ws.recv()
            if message is None:
                ws.close()
                break
        return HttpResponse()
    elif request.method == 'GET':
        if request.META.get('HTTP_ACCEPT') == 'text/event-stream':
            resp = HttpResponse(content_type='text/event-stream')
            set_hold_stream(request, headline_id)
            return resp
        else:
            wait = request.META.get('HTTP_WAIT')
            if wait:
                wait = int(wait)
                if wait < 1:
                    wait = None
                if wait > 300:
                    wait = 300
            inm = request.META.get('HTTP_IF_NONE_MATCH')
            etag = '"%s"' % calendar.timegm(h.date.utctimetuple())
            if inm == etag:
                resp = HttpResponseNotModified()
                if wait:
                    set_hold_longpoll(request, headline_id, timeout=wait)
            else:
                resp = _json_response(h.to_data())
            resp['ETag'] = etag
            return resp
    elif request.method == 'PUT':
        hdata = json.loads(request.read())
        h.type = hdata['type']
        h.title = hdata.get('title', '')
        h.text = hdata.get('text', '')
        h.save()
        hdata = h.to_data()
        hjson = json.dumps(hdata)
        etag = '"%s"' % calendar.timegm(h.date.utctimetuple())
        rheaders = {'Content-Type': 'application/json', 'ETag': etag}
        hpretty = json.dumps(hdata, indent=4) + '\n'
        formats = list()
        formats.append(HttpResponseFormat(body=hpretty, headers=rheaders))
        formats.append(HttpStreamFormat('event: update\ndata: %s\n\n' % hjson))
        formats.append(WebSocketMessageFormat(hjson))
        publish(headline_id, formats)
        resp = _json_response(hdata)
        resp['ETag'] = etag
        return resp
    else:
        return HttpResponseNotAllowed(['GET', 'PUT'])
Esempio n. 4
0
def todos(request, list_id):
	if request.method == 'OPTIONS':
		resp = HttpResponse()
		resp['Access-Control-Max-Age'] = '3600'
		return resp

	if request.method == 'HEAD':
		last_cursor = TodoItem.get_last_cursor(list_id)
		resp = HttpResponse()
		resp['Link'] = _changes_link(list_id, last_cursor.cur)
		return resp
	elif request.method == 'GET':
		stream = request.GET.get('stream')
		after = request.GET.get('after_change')
		wait = request.META.get('HTTP_WAIT')
		if stream:
			stream = (stream == 'true')
		if wait:
			wait = int(wait)

		if stream:
			set_hold_stream(request, Channel('todos-%s' % list_id))
			return HttpResponse(content_type='text/plain')
		else:
			if after:
				try:
					items, last_cursor = TodoItem.get_after(list_id, after)
				except TodoItem.DoesNotExist:
					return HttpResponseNotFound()
			else:
				items, last_cursor = TodoItem.get_all(list_id)
			resp = _list_response(list_id, items)
			resp['Link'] = _changes_link(list_id, last_cursor.cur)
			if len(items) == 0 and wait:
				set_hold_longpoll(request, Channel('todos-%s' % list_id, prev_id=last_cursor.cur), timeout=wait)
			return resp
	elif request.method == 'POST':
		params = json.loads(request.body)
		i = TodoItem(list_id=list_id)
		if 'text' in params:
			i.text = params['text']
		if 'completed' in params:
			if not isinstance(params['completed'], bool):
				return HttpResponseBadRequest('completed must be a bool\n', content_type='text/plain')
			i.completed = params['completed']
		try:
			cursor = i.save()
		except TodoItem.LimitError:
			return HttpResponseForbidden('limit reached\n', content_type='text/plain')
		if cursor.cur != cursor.prev:
			_publish_item(list_id, i, cursor)
		resp = _item_response(i, status=201)
		resp['Location'] = reverse('todos-item', args=[list_id, i.id])
		return resp
	else:
		return HttpResponseNotAllowed(['HEAD', 'GET', 'POST'])
Esempio n. 5
0
	def process_view(self, request, view_func, view_args, view_kwargs):
		# require grip middleware
		assert hasattr(request, 'grip_proxied'), 'GripMiddleware must run before LiveResourceMiddleware'

		if getattr(view_func, 'live', False):
			# parse wait header
			wait = request.META.get('HTTP_WAIT')
			if wait is not None:
				try:
					wait = int(wait)
				except:
					return HttpResponseBadRequest('Invalid Wait header specified.\n')

				if wait < 1:
					wait = None
				elif wait > WAIT_MAX:
					wait = WAIT_MAX

			resp = view_func(request, *view_args, **view_kwargs)

			if wait:
				if not request.grip_proxied:
					return HttpResponse('Error: Realtime request not supported. Set up Pushpin or Fanout.\n', status=501)

				if hasattr(resp, 'multi_info'):
					channels = list()
					for ri in resp.multi_info:
						try:
							channel = channel_object_for_request(request, ri, True)
						except:
							return HttpResponse('Resource cannot be used for updates.\n', status=501)
						channels.append(channel)
					set_hold_longpoll(resp, channels, timeout=wait)
				else:
					ri = get_resourceinfo(canonical_uri(request.path), resp)
					if ri:
						try:
							channel = channel_object_for_request(request, ri, True)
						except:
							return HttpResponse('Resource cannot be used for updates.\n', status=501)
						set_hold_longpoll(resp, channel, timeout=wait)

			return resp
Esempio n. 6
0
def items(req, inbox_id):
    if req.method == 'GET':
        try:
            db.inbox_refresh(inbox_id)
        except redis_ops.InvalidId:
            return HttpResponseBadRequest('Bad Request: Invalid id\n')
        except redis_ops.ObjectDoesNotExist:
            return HttpResponseNotFound('Not Found\n')
        except:
            return HttpResponse('Service Unavailable\n', status=503)

        order = req.GET.get('order')
        if order and order not in ('created', '-created'):
            return HttpResponseBadRequest('Bad Request: Invalid order value\n')

        if not order:
            order = 'created'

        imax = req.GET.get('max')
        if imax:
            try:
                imax = int(imax)
                if imax < 1:
                    raise ValueError('max too small')
            except:
                return HttpResponseBadRequest(
                    'Bad Request: Invalid max value\n')

        if not imax or imax > 50:
            imax = 50

        since = req.GET.get('since')
        since_id = None
        since_cursor = None
        if since:
            if since.startswith('id:'):
                since_id = since[3:]
            elif since.startswith('cursor:'):
                since_cursor = since[7:]
            else:
                return HttpResponseBadRequest(
                    'Bad Request: Invalid since value\n')

        # at the moment, cursor is identical to id
        item_id = None
        if since_id:
            item_id = since_id
        elif since_cursor:
            item_id = since_cursor

        if order == 'created':
            try:
                items, last_id = db.inbox_get_items_after(
                    inbox_id, item_id, imax)
            except redis_ops.InvalidId:
                return HttpResponseBadRequest('Bad Request: Invalid id\n')
            except redis_ops.ObjectDoesNotExist:
                return HttpResponseNotFound('Not Found\n')
            except:
                return HttpResponse('Service Unavailable\n', status=503)

            out = dict()
            out['last_cursor'] = last_id
            out_items = list()
            for i in items:
                out_items.append(
                    _convert_item(
                        i, not db.request_is_pending(inbox_id, i['id'])))
            out['items'] = out_items

            if len(out_items) == 0:
                set_hold_longpoll(
                    req, Channel(grip_prefix + 'inbox-%s' % inbox_id, last_id))

            return HttpResponse(json.dumps(out) + '\n',
                                content_type='application/json')
        else:  # -created
            try:
                items, last_id, eof = db.inbox_get_items_before(
                    inbox_id, item_id, imax)
            except redis_ops.InvalidId:
                return HttpResponseBadRequest('Bad Request: Invalid id\n')
            except redis_ops.ObjectDoesNotExist:
                return HttpResponseNotFound('Not Found\n')
            except:
                return HttpResponse('Service Unavailable\n', status=503)

            out = dict()
            if not eof and last_id:
                out['last_cursor'] = last_id
            out_items = list()
            for i in items:
                out_items.append(
                    _convert_item(
                        i, not db.request_is_pending(inbox_id, i['id'])))
            out['items'] = out_items
            return HttpResponse(json.dumps(out) + '\n',
                                content_type='application/json')
    else:
        return HttpResponseNotAllowed(['GET'])
Esempio n. 7
0
def hit(req, inbox_id):
    try:
        inbox = db.inbox_get(inbox_id)
    except redis_ops.InvalidId:
        return HttpResponseBadRequest('Bad Request: Invalid id\n')
    except redis_ops.ObjectDoesNotExist:
        return HttpResponseNotFound('Not Found\n')
    except:
        return HttpResponse('Service Unavailable\n', status=503)

    response_mode = inbox.get('response_mode')
    if not response_mode:
        response_mode = 'auto'

    # pubsubhubbub verify request?
    hub_challenge = req.GET.get('hub.challenge')

    if response_mode == 'wait' or (response_mode == 'wait-verify'
                                   and hub_challenge):
        respond_now = False
    else:
        respond_now = True

    item = _req_to_item(req)
    if hub_challenge:
        item['type'] = 'hub-verify'
    else:
        item['type'] = 'normal'

    try:
        item_id, prev_id, item_created = db.inbox_append_item(inbox_id, item)
        db.inbox_clear_expired_items(inbox_id)
    except redis_ops.InvalidId:
        return HttpResponseBadRequest('Bad Request: Invalid id\n')
    except redis_ops.ObjectDoesNotExist:
        return HttpResponseNotFound('Not Found\n')
    except:
        return HttpResponse('Service Unavailable\n', status=503)

    item['id'] = item_id
    item['created'] = item_created

    item = _convert_item(item, respond_now)

    hr_headers = dict()
    hr_headers['Content-Type'] = 'application/json'
    hr = dict()
    hr['last_cursor'] = item_id
    hr['items'] = [item]
    hr_body = json.dumps(hr) + '\n'
    hs_body = json.dumps(item) + '\n'

    formats = list()
    formats.append(HttpResponseFormat(headers=hr_headers, body=hr_body))
    formats.append(HttpStreamFormat(hs_body))
    publish(grip_prefix + 'inbox-%s' % inbox_id,
            formats,
            id=item_id,
            prev_id=prev_id)

    if respond_now:
        if hub_challenge:
            return HttpResponse(hub_challenge)
        else:
            return HttpResponse('Ok\n')
    else:
        # wait for the user to respond
        db.request_add_pending(inbox_id, item_id)
        set_hold_longpoll(req,
                          grip_prefix + 'wait-%s-%s' % (inbox_id, item_id))
        return HttpResponse('Service Unavailable\n',
                            status=503,
                            content_type='text/html')
Esempio n. 8
0
def items(req, inbox_id):
	if req.method == 'GET':
		try:
			db.inbox_refresh(inbox_id)
		except redis_ops.InvalidId:
			return HttpResponseBadRequest('Bad Request: Invalid id\n')
		except redis_ops.ObjectDoesNotExist:
			return HttpResponseNotFound('Not Found\n')
		except:
			return HttpResponse('Service Unavailable\n', status=503)

		order = req.GET.get('order')
		if order and order not in ('created', '-created'):
			return HttpResponseBadRequest('Bad Request: Invalid order value\n')

		if not order:
			order = 'created'

		imax = req.GET.get('max')
		if imax:
			try:
				imax = int(imax)
				if imax < 1:
					raise ValueError('max too small')
			except:
				return HttpResponseBadRequest('Bad Request: Invalid max value\n')

		if not imax or imax > 50:
			imax = 50

		since = req.GET.get('since')
		since_id = None
		since_cursor = None
		if since:
			if since.startswith('id:'):
				since_id = since[3:]
			elif since.startswith('cursor:'):
				since_cursor = since[7:]
			else:
				return HttpResponseBadRequest('Bad Request: Invalid since value\n')

		# at the moment, cursor is identical to id
		item_id = None
		if since_id:
			item_id = since_id
		elif since_cursor:
			item_id = since_cursor

		if order == 'created':
			try:
				items, last_id = db.inbox_get_items_after(inbox_id, item_id, imax)
			except redis_ops.InvalidId:
				return HttpResponseBadRequest('Bad Request: Invalid id\n')
			except redis_ops.ObjectDoesNotExist:
				return HttpResponseNotFound('Not Found\n')
			except:
				return HttpResponse('Service Unavailable\n', status=503)

			out = dict()
			out['last_cursor'] = last_id
			out_items = list()
			for i in items:
				out_items.append(_convert_item(i, not db.request_is_pending(inbox_id, i['id'])))
			out['items'] = out_items

			if len(out_items) == 0:
				set_hold_longpoll(req, Channel(grip_prefix + 'inbox-%s' % inbox_id, last_id))

			return HttpResponse(json.dumps(out) + '\n', content_type='application/json')
		else: # -created
			try:
				items, last_id, eof = db.inbox_get_items_before(inbox_id, item_id, imax)
			except redis_ops.InvalidId:
				return HttpResponseBadRequest('Bad Request: Invalid id\n')
			except redis_ops.ObjectDoesNotExist:
				return HttpResponseNotFound('Not Found\n')
			except:
				return HttpResponse('Service Unavailable\n', status=503)

			out = dict()
			if not eof and last_id:
				out['last_cursor'] = last_id
			out_items = list()
			for i in items:
				out_items.append(_convert_item(i, not db.request_is_pending(inbox_id, i['id'])))
			out['items'] = out_items
			return HttpResponse(json.dumps(out) + '\n', content_type='application/json')
	else:
		return HttpResponseNotAllowed(['GET'])
Esempio n. 9
0
def hit(req, inbox_id):
	if len(req.grip.last) > 0:
		for channel, last_id in req.grip.last.iteritems():
			break
		set_hold_longpoll(req, Channel(channel, last_id))
		return HttpResponse('Service Unavailable\n', status=503, content_type='text/html')

	try:
		inbox = db.inbox_get(inbox_id)
	except redis_ops.InvalidId:
		return HttpResponseBadRequest('Bad Request: Invalid id\n')
	except redis_ops.ObjectDoesNotExist:
		return HttpResponseNotFound('Not Found\n')
	except:
		return HttpResponse('Service Unavailable\n', status=503)

	response_mode = inbox.get('response_mode')
	if not response_mode:
		response_mode = 'auto'

	# pubsubhubbub verify request?
	hub_challenge = req.GET.get('hub.challenge')

	if response_mode == 'wait' or (response_mode == 'wait-verify' and hub_challenge):
		respond_now = False
	else:
		respond_now = True

	item = _req_to_item(req)
	if hub_challenge:
		item['type'] = 'hub-verify'
	else:
		item['type'] = 'normal'

	try:
		item_id, prev_id, item_created = db.inbox_append_item(inbox_id, item)
		db.inbox_clear_expired_items(inbox_id)
	except redis_ops.InvalidId:
		return HttpResponseBadRequest('Bad Request: Invalid id\n')
	except redis_ops.ObjectDoesNotExist:
		return HttpResponseNotFound('Not Found\n')
	except:
		return HttpResponse('Service Unavailable\n', status=503)

	item['id'] = item_id
	item['created'] = item_created

	item = _convert_item(item, respond_now)

	hr_headers = dict()
	hr_headers['Content-Type'] = 'application/json'
	hr = dict()
	hr['last_cursor'] = item_id
	hr['items'] = [item]
	hr_body = json.dumps(hr) + '\n'
	hs_body = json.dumps(item) + '\n'

	formats = list()
	formats.append(HttpResponseFormat(headers=hr_headers, body=hr_body))
	formats.append(HttpStreamFormat(hs_body))
	publish(grip_prefix + 'inbox-%s' % inbox_id, formats, id=item_id, prev_id=prev_id)

	if respond_now:
		if hub_challenge:
			return HttpResponse(hub_challenge)
		else:
			return HttpResponse('Ok\n')
	else:
		# wait for the user to respond
		db.request_add_pending(inbox_id, item_id)
		set_hold_longpoll(req, Channel(grip_prefix + 'wait-%s-%s' % (inbox_id, item_id), '0'))
		return HttpResponse('Service Unavailable\n', status=503, content_type='text/html')
Esempio n. 10
0
def todos(request, list_id):
    if request.method == 'OPTIONS':
        resp = HttpResponse()
        resp['Access-Control-Max-Age'] = '3600'
        return resp

    if request.method == 'HEAD':
        last_cursor = TodoItem.get_last_cursor(list_id)
        resp = HttpResponse()
        resp['Link'] = _changes_link(list_id, last_cursor.cur)
        return resp
    elif request.method == 'GET':
        stream = request.GET.get('stream')
        after = request.GET.get('after_change')
        wait = request.META.get('HTTP_WAIT')
        if stream:
            stream = (stream == 'true')
        if wait:
            wait = int(wait)

        if stream:
            set_hold_stream(request, Channel('todos-%s' % list_id))
            return HttpResponse(content_type='text/plain')
        else:
            if after:
                try:
                    items, last_cursor = TodoItem.get_after(list_id, after)
                except TodoItem.DoesNotExist:
                    return HttpResponseNotFound()
            else:
                items, last_cursor = TodoItem.get_all(list_id)
            resp = _list_response(list_id, items)
            resp['Link'] = _changes_link(list_id, last_cursor.cur)
            if len(items) == 0 and wait:
                set_hold_longpoll(request,
                                  Channel('todos-%s' % list_id,
                                          prev_id=last_cursor.cur),
                                  timeout=wait)
            return resp
    elif request.method == 'POST':
        params = json.loads(request.body)
        i = TodoItem(list_id=list_id)
        if 'text' in params:
            i.text = params['text']
        if 'completed' in params:
            if not isinstance(params['completed'], bool):
                return HttpResponseBadRequest('completed must be a bool\n',
                                              content_type='text/plain')
            i.completed = params['completed']
        try:
            cursor = i.save()
        except TodoItem.LimitError:
            return HttpResponseForbidden('limit reached\n',
                                         content_type='text/plain')
        if cursor.cur != cursor.prev:
            _publish_item(list_id, i, cursor)
        resp = _item_response(i, status=201)
        resp['Location'] = reverse('todos-item', args=[list_id, i.id])
        return resp
    else:
        return HttpResponseNotAllowed(['HEAD', 'GET', 'POST'])