示例#1
0
def updated(uri, prev_checkpoint=None):
	uri = canonical_uri(uri)

	resp = internal_request(uri)
	resp_headers = dict()
	for k, v in resp.items():
		resp_headers[k] = v

	if len(resp.content) > 0:
		try:
			resp_body = json.loads(resp.content)
		except:
			resp_body = ''
	else:
		resp_body = ''

	msg = dict()
	msg['type'] = 'event'
	msg['uri'] = uri
	msg['headers'] = resp_headers
	msg['body'] = resp_body

	formats = list()
	formats.append(HttpResponseFormat(code=resp.status_code, headers=resp_headers, body=resp.content))
	formats.append(WebSocketMessageFormat(json.dumps(msg)))

	channel = channel_for_uri(uri, 'value')

	# TODO: id, prev_id
	publish(channel, formats)
示例#2
0
文件: views.py 项目: fanout/test-api
def publish_message(message):
    # Get the most recent sent message from the database (empty string by
    #   default).
    m = LastMessage.get_only()

    # Generate ETags of the previous and current messages, using the same
    #   algorithm as the GET handler.
    etag = '"%s"' % hashlib.md5(message).hexdigest()
    prev_etag = '"%s"' % hashlib.md5(m.text).hexdigest()

    # Save the current message to the database, overwriting the previous.
    m.text = message
    m.save()

    # Prepare headers for the HTTP request and HTTP response delivery
    #   mechanisms.
    headers = {'Content-Type': 'text/plain', 'ETag': etag}

    formats = []

    # Prepare the message in four different formats.
    formats.append(HttpResponseFormat(headers=headers, body=message + '\n'))
    formats.append(HttpStreamFormat(message + '\n'))
    formats.append(WebSocketMessageFormat(message))
    formats.append(HttpRequestFormat('POST', headers=headers,
        body=message + '\n'))

    # Send to the proxy and/or Fanout.
    publish('messages', formats, id=etag, prev_id=prev_etag)
示例#3
0
def publish_event(channel,
                  event_type,
                  data,
                  pub_id,
                  pub_prev_id,
                  skip_user_ids=[]):
    from django_grip import publish

    content_filters = []
    if pub_id:
        event_id = '%I'
        content_filters.append('build-id')
    else:
        event_id = None
    content = sse_encode_event(event_type,
                               data,
                               event_id=event_id,
                               escape=bool(pub_id))
    meta = {}
    if skip_user_ids:
        meta['skip_users'] = ','.join(skip_user_ids)
    publish('events-%s' % quote(channel),
            HttpStreamFormat(content, content_filters=content_filters),
            id=pub_id,
            prev_id=pub_prev_id,
            meta=meta)
示例#4
0
def expire_requests():
	reqs = db.request_take_expired()
	headers = dict()
	headers['Content-Type'] = 'text/html'
	body = 'Service Unavailable\n'
	for r in reqs:
		publish(grip_prefix + 'wait-%s-%s' % (r[0], r[1]), HttpResponseFormat(code=503, headers=headers, body=body))
	return len(reqs)
示例#5
0
def broadcast(request):
    ws = request.wscontext
    print(ws.in_events[0])

    # if this is a new connection, accept it and subscribe it to a channel
    if ws.is_opening():
        ws.accept()
        publish('test', WebSocketMessageFormat('broadcast\n'))
示例#6
0
def expire_requests():
	reqs = db.request_take_expired()
	headers = dict()
	headers['Content-Type'] = 'text/html'
	body = 'Service Unavailable\n'
	for r in reqs:
		publish(grip_prefix + 'wait-%s-%s' % (r[0], r[1]), HttpResponseFormat(code=503, headers=headers, body=body), id='1', prev_id='0')
	return len(reqs)
示例#7
0
def broadcast(request):
    if request.method == 'POST':
        # publish data to all clients that are connected to the echo endpoint
        data = request.POST['data']
        publish('test', WebSocketMessageFormat(data))
        return HttpResponse('Ok\n')
    else:
        return HttpResponseNotAllowed(['POST'])
示例#8
0
文件: views.py 项目: masnth/headline
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'])
示例#9
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'])
示例#10
0
def _publish_item(list_id, item, cursor):
    data = item.to_data()
    _add_totals(list_id, data)
    body = _json_data([data]) + '\n'
    stream_data = deepcopy(data)
    stream_data['change-id'] = str(cursor.cur)
    stream_content = _json_data(stream_data, False) + '\n'
    headers = {'Link': _changes_link(list_id, cursor.cur)}
    formats = []
    formats.append(HttpResponseFormat(headers=headers, body=body))
    formats.append(HttpStreamFormat(stream_content))
    publish('todos-%s' % list_id, formats, id=cursor.cur, prev_id=cursor.prev)
示例#11
0
def _publish_item(list_id, item, cursor):
	data = item.to_data()
	_add_totals(list_id, data)
	body = _json_data([data]) + '\n'
	stream_data = deepcopy(data)
	stream_data['change-id'] = str(cursor.cur)
	stream_content = _json_data(stream_data, False) + '\n'
	headers = {'Link': _changes_link(list_id, cursor.cur)}
	formats = []
	formats.append(HttpResponseFormat(headers=headers, body=body))
	formats.append(HttpStreamFormat(stream_content))
	publish('todos-%s' % list_id, formats, id=cursor.cur, prev_id=cursor.prev)
示例#12
0
def publish_kick(user_id, channel):
    from django_grip import publish

    msg = 'Permission denied to channels: %s' % channel
    data = {'condition': 'forbidden', 'text': msg, 'channels': [channel]}
    content = sse_encode_event('stream-error', data, event_id='error')
    meta = {'require_sub': 'events-%s' % channel}
    publish('user-%s' % user_id,
            HttpStreamFormat(content),
            id='kick-1',
            meta=meta)
    publish('user-%s' % user_id,
            HttpStreamFormat(close=True),
            id='kick-2',
            prev_id='kick-1',
            meta=meta)
示例#13
0
def respond(req, inbox_id, item_id):
    if req.method == 'POST':
        try:
            content = json.loads(req.body)
        except:
            return HttpResponseBadRequest(
                'Bad Request: Body must be valid JSON\n')

        try:
            code = content.get('code')
            if code is not None:
                code = int(code)
            else:
                code = 200

            reason = content.get('reason')
            headers = content.get('headers')

            if 'body-bin' in content:
                body = b64decode(content['body-bin'])
            elif 'body' in content:
                body = content['body']
            else:
                body = ''
        except:
            return HttpResponseBadRequest(
                'Bad Request: Bad format of response\n')

        try:
            db.request_remove_pending(inbox_id, item_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)

        publish(
            grip_prefix + 'wait-%s-%s' % (inbox_id, item_id),
            HttpResponseFormat(code=code,
                               reason=reason,
                               headers=headers,
                               body=body))

        return HttpResponse('Ok\n')
    else:
        return HttpResponseNotAllowed(['POST'])
示例#14
0
def inbox(req, inbox_id):
    if req.method == 'GET':
        host = req.META.get('HTTP_HOST')
        if not host:
            return HttpResponseBadRequest('Bad Request: No \'Host\' header\n')

        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)

        out = dict()
        out['id'] = inbox_id
        out['base_url'] = 'http://' + host + '/i/' + inbox_id + '/'
        out['ttl'] = inbox['ttl']
        response_mode = inbox.get('response_mode')
        if not response_mode:
            response_mode = 'auto'
        out['response_mode'] = response_mode
        return HttpResponse(json.dumps(out) + '\n',
                            content_type='application/json')
    elif req.method == 'DELETE':
        try:
            db.inbox_delete(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)

        # we'll push a 404 to any long polls because we're that cool
        publish(
            grip_prefix + 'inbox-%s' % inbox_id,
            HttpResponseFormat(code=404,
                               headers={'Content-Type': 'text/html'},
                               body='Not Found\n'))

        return HttpResponse('Deleted\n')
    else:
        return HttpResponseNotAllowed(['GET', 'DELETE'])
    def wrapper(self, request, room_id, *args, **kwargs):
        """ Automatically push the data returned from view_func. """

        response = view_func(self, request, room_id, *args, **kwargs)

        # If we got a JSON response, we'll want to publish this out
        if isinstance(response, JsonResponse):
            if request.method == 'POST':
                event = "create"
            elif request.method == 'DELETE':
                event = "delete"
            else:
                event = "update"

            # Got back a data object that needs to be published
            update_content = [HttpStreamFormat('event: %s\ndata: %s\n\n' % (event, response.content))]
            publish(self._stream_name(room_id), update_content)

        return response
示例#16
0
def inbox(req, inbox_id):
	if req.method == 'GET':
		host = req.META.get('HTTP_HOST')
		if not host:
			return HttpResponseBadRequest('Bad Request: No \'Host\' header\n')

		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)

		out = dict()
		out['id'] = inbox_id
		out['base_url'] = 'http://' + host + '/i/' + inbox_id + '/'
		out['ttl'] = inbox['ttl']
		response_mode = inbox.get('response_mode')
		if not response_mode:
			response_mode = 'auto'
		out['response_mode'] = response_mode
		return HttpResponse(json.dumps(out) + '\n', content_type='application/json')
	elif req.method == 'DELETE':
		try:
			db.inbox_delete(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)

		# we'll push a 404 to any long polls because we're that cool
		publish(grip_prefix + 'inbox-%s' % inbox_id, HttpResponseFormat(code=404, headers={'Content-Type': 'text/html'}, body='Not Found\n'))

		return HttpResponse('Deleted\n')
	else:
		return HttpResponseNotAllowed(['GET', 'DELETE'])
示例#17
0
def respond(req, inbox_id, item_id):
	if req.method == 'POST':
		try:
			content = json.loads(req.body)
		except:
			return HttpResponseBadRequest('Bad Request: Body must be valid JSON\n')

		try:
			code = content.get('code')
			if code is not None:
				code = int(code)
			else:
				code = 200

			reason = content.get('reason')
			headers = content.get('headers')

			if 'body-bin' in content:
				body = b64decode(content['body-bin'])
			elif 'body' in content:
				body = content['body']
			else:
				body = ''
		except:
			return HttpResponseBadRequest('Bad Request: Bad format of response\n')

		try:
			db.request_remove_pending(inbox_id, item_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)

		publish(grip_prefix + 'wait-%s-%s' % (inbox_id, item_id), HttpResponseFormat(code=code, reason=reason, headers=headers, body=body), id='1', prev_id='0')

		return HttpResponse('Ok\n')
	else:
		return HttpResponseNotAllowed(['POST'])
示例#18
0
    def handle(self, *args, **options):
        c = Consumer(settings.KAFKA_CONSUMER_CONFIG)

        c.subscribe(['^.*'])

        self.stdout.write('subscribed')

        try:
            while True:
                msg = c.poll(timeout=1)

                if msg is None:
                    continue

                if msg.error():
                    if msg.error().code() == KafkaError._PARTITION_EOF:
                        continue
                    else:
                        raise KafkaException(msg.error())

                # skip internal channels
                if msg.topic().startswith('__'):
                    continue

                try:
                    data = msg.value().decode('utf-8')
                except Exception:
                    self.stdout.write('%s: message is not valid utf-8: %s' %
                                      (msg.topic(), repr(msg.value())))
                    continue

                publish(msg.topic(), HttpStreamFormat(sse_encode(data)))

        except KeyboardInterrupt:
            pass

        c.close()
示例#19
0
def publish_board(board):
    players = Player.get_top_for_board(board, limit=5)
    publish(
        str(board.id),
        HttpStreamFormat('event: update\ndata: %s\n\n' %
                         _board_json(board, players, pretty=False)))
示例#20
0
def document_change(request, document_id):

    if request.method == 'GET':

        link = False
        sse = False
        if request.GET.get('link') == 'true':
            link = True
            sse = True
        else:
            accept = request.META.get('HTTP_ACCEPT')
            if accept and accept.find('text/event-stream') != -1:
                sse = True

        after = None

        grip_last = request.META.get('HTTP_GRIP_LAST')
        if grip_last:
            at = grip_last.find('last-id=')
            if at == -1:
                raise ValueError('invalid Grip-Last header')
            at += 8
            after = int(grip_last[at:])

        if after is None and sse:
            last_id = request.META.get('Last-Event-ID')
            if last_id:
                after = int(last_id)

        if after is None and sse:
            last_id = request.GET.get('lastEventId')
            if last_id:
                after = int(last_id)

        if after is None:
            afterstr = request.GET.get('after')
            if afterstr:
                after = int(afterstr)

        try:
            doc = Document.objects.get(eid=document_id)
            if after is not None:
                if after > doc.version:
                    return HttpResponseNotFound('version in the future')
                changes = DocumentChange.objects.filter(
                    document=doc,
                    version__gt=after).order_by('version')[:50]
                out = [c.export() for c in changes]
                if len(out) > 0:
                    last_version = out[-1]['version']
                else:
                    last_version = after
            else:
                out = []
                last_version = doc.version
        except Document.DoesNotExist:
            if after is not None and after > 0:
                return HttpResponseNotFound('version in the future')
            out = []
            last_version = 0

        if sse:
            body = ''
            if not link:
                body += 'event: opened\ndata:\n\n'
            for i in out:
                event = 'id: %d\nevent: change\ndata: %s\n\n' % (
                    i['version'], json.dumps(i))
                body += event
            resp = HttpResponse(body, content_type='text/event-stream')
            parsed = urlparse(reverse('document-changes', args=[document_id]))
            resp['Grip-Link'] = '<%s?link=true&after=%d>; rel=next' % (
                parsed.path, last_version)
            if len(out) < 50:
                resp['Grip-Hold'] = 'stream'
                resp['Grip-Channel'] = 'document-%s; prev-id=%s' % (
                    document_id, last_version)
                resp['Grip-Keep-Alive'] = 'event: keep-alive\\ndata:\\n\\n; format=cstring; timeout=20'

            # print(resp.content)

            return resp
        else:
            return JsonResponse({'changes': out})

    elif request.method == 'POST':
        opdata = json.loads(request.POST['op'])
        for i in opdata:
            if not isinstance(i, int) and not isinstance(i, str):
                return HttpResponseBadRequest('invalid operation');

        op = TextOperation(opdata)

        request_id = request.POST['request-id']
        parent_version = int(request.POST['parent-version'])
        doc = _doc_get_or_create(document_id)

        saved = False
        with transaction.atomic():
            doc = Document.objects.select_for_update().get(id=doc.id)
            try:
                # already submitted?
                c = DocumentChange.objects.get(
                    document=doc,
                    request_id=request_id,
                    parent_version=parent_version)
            except DocumentChange.DoesNotExist:
                changes_since = DocumentChange.objects.filter(
                    document=doc,
                    version__gt=parent_version,
                    version__lte=doc.version).order_by('version')

                for c in changes_since:
                    op2 = TextOperation(json.loads(c.data))
                    try:
                        op, _ = TextOperation.transform(op, op2)
                    except:
                        return HttpResponseBadRequest(
                            'unable to transform against version %d' % c.version)

                try:
                    doc.content = op(doc.content)
                except:
                    return HttpResponseBadRequest(
                        'unable to apply %s to version %d' % (
                            json.dumps(op.ops), doc.version))

                next_version = doc.version + 1

                c = DocumentChange(
                    document=doc,
                    version=next_version,
                    request_id=request_id,
                    parent_version=parent_version,
                    data=json.dumps(op.ops))
                c.save()
                doc.version = next_version
                doc.save()
                saved = True

        if saved:
            event = 'id: %d\nevent: change\ndata: %s\n\n' % (
                c.version, json.dumps(c.export()))
            publish(
                'document-%s' % document_id,
                HttpStreamFormat(event),
                id=str(c.version),
                prev_id=str(c.version - 1))

        return JsonResponse({'version': c.version})
    else:
        return HttpResponseNotAllowed(['GET', 'POST'])
示例#21
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')
def document_changes(request, document_id):
	url = REPLICA_URLS[CURRENT_PRIMARY]+'/api/documents/{}/changes/'.format(document_id)
	print('url here goes', url)
	if request.method == 'GET':
		gchannel = 'document-{}'.format(document_id)
		link = False
		sse = False
		if request.GET.get('link') == 'true':
			link = True
			sse = True
		else:
			accept = request.META.get('HTTP_ACCEPT')
			if accept and accept.find('text/event-stream') != -1:
				sse = True

		after = None
		last_id = request.grip.last.get(gchannel)
		if last_id:
			after = int(last_id)
		
		if after is None and sse:
			last_id = request.META.get('Last-Event-ID')
			if last_id:
				after = int(last_id)

		if after is None and sse:
			last_id = request.GET.get('lastEventId')
			if last_id:
				after = int(last_id)

		if after is None:
			afterstr = request.GET.get('after')
			if afterstr:
				after = int(afterstr)


		payload = request.GET.dict()
		payload['from-master'] = True
		response = requests.get(url, payload)

		resp_content = json.loads(response.text)
		if "success" in resp_content:
			if resp_content["success"]:
				response = HttpResponse(resp_content['body'], content_type='text/event-stream')
				parsed = urlparse(reverse('document-changes', args=[document_id]))
				instruct = request.grip.start_instruct()
				instruct.set_next_link('{}?link=true&after={}'.format(parsed.path, resp_content['last_version']))
				if len(resp_content['out']) < 50:
					instruct.set_hold_stream()
					instruct.add_channel(Channel(resp_content['gchannel'], prev_id=str(resp_content['last_version'])))
					instruct.set_keep_alive('event: keep-alive\ndata:\n\n; format=cstring', 20)
		else:
			response = HttpResponseNotFound('version in the future')

	elif request.method == 'POST':
		payload = request.POST.dict()
		payload['from-master'] = True
		response = requests.post(url, payload)
		print('\n\n-----',response,response.status_code,'\n\n')
		if response.status_code == 200:
			resp_content = json.loads(response.text)
			print('resp',resp_content)
			if "success" in resp_content:
				if resp_content["success"]:
					publish(
						resp_content['gchannel'],
						HttpStreamFormat(json.loads(resp_content['event'])),
						id=str(resp_content['version']),
						prev_id=str(resp_content['version']-1))

				response = JsonResponse({'version': resp_content['version']})

		elif response.status_code == 500:
			response = HttpResponseBadRequest(response.text)
		else:
			response = HttpResponseNotFound('invalid')

	return response		
示例#23
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')
示例#24
0
def document_changes(request, document_id):
	gchannel = 'document-{}'.format(document_id)

	if request.method == 'GET':
		link = False
		sse = False
		if request.GET.get('link') == 'true':
			link = True
			sse = True
		else:
			accept = request.META.get('HTTP_ACCEPT')
			if accept and accept.find('text/event-stream') != -1:
				sse = True

		after = None

		last_id = request.grip.last.get(gchannel)
		if last_id:
			after = int(last_id)

		if after is None and sse:
			last_id = request.META.get('Last-Event-ID')
			if last_id:
				after = int(last_id)

		if after is None and sse:
			last_id = request.GET.get('lastEventId')
			if last_id:
				after = int(last_id)

		if after is None:
			afterstr = request.GET.get('after')
			if afterstr:
				after = int(afterstr)

		try:
			doc = Document.objects.get(eid=document_id)
			if after is not None:
				if after > doc.version:
					return HttpResponseNotFound('version in the future')
				changes = DocumentChange.objects.filter(
					document=doc,
					version__gt=after).order_by('version')[:50]
				out = [c.export() for c in changes]
				if len(out) > 0:
					last_version = out[-1]['version']
				else:
					last_version = after
			else:
				out = []
				last_version = doc.version
		except Document.DoesNotExist:
			if after is not None and after > 0:
				return HttpResponseNotFound('version in the future')
			out = []
			last_version = 0

		if sse:
			body = ''
			if not link:
				body += 'event: opened\ndata:\n\n'
			for i in out:
				event = 'id: {}\nevent: change\ndata: {}\n\n'.format(
					i['version'], json.dumps(i))
				body += event
			resp = HttpResponse(body, content_type='text/event-stream')
			parsed = urlparse.urlparse(reverse('document-changes', args=[document_id]))
			instruct = request.grip.start_instruct()
			instruct.set_next_link('{}?link=true&after={}'.format(
				parsed.path, last_version))
			if len(out) < 50:
				instruct.set_hold_stream()
				instruct.add_channel(Channel(gchannel, prev_id=str(last_version)))
				instruct.set_keep_alive('event: keep-alive\ndata:\n\n; format=cstring', 20)
			return resp
		else:
			return JsonResponse({'changes': out})
	elif request.method == 'POST':
		opdata = json.loads(request.POST['op'])
		for i in opdata:
			if not isinstance(i, int) and not isinstance(i, basestring):
				return HttpResponseBadRequest('invalid operation');

		op = TextOperation(opdata)

		request_id = request.POST['request-id']
		parent_version = int(request.POST['parent-version'])
		doc = _doc_get_or_create(document_id)

		saved = False
		with transaction.atomic():
			doc = Document.objects.select_for_update().get(id=doc.id)
			try:
				# already submitted?
				c = DocumentChange.objects.get(
					document=doc,
					request_id=request_id,
					parent_version=parent_version)
			except DocumentChange.DoesNotExist:
				changes_since = DocumentChange.objects.filter(
					document=doc,
					version__gt=parent_version,
					version__lte=doc.version).order_by('version')

				for c in changes_since:
					op2 = TextOperation(json.loads(c.data))
					try:
						op, _ = TextOperation.transform(op, op2)
					except:
						return HttpResponseBadRequest(
							'unable to transform against version {}'.format(c.version))

				try:
					doc.content = op(doc.content)
				except:
					return HttpResponseBadRequest(
						'unable to apply {} to version {}'.format(
						json.dumps(op.ops), doc.version))

				next_version = doc.version + 1
				c = DocumentChange(
					document=doc,
					version=next_version,
					request_id=request_id,
					parent_version=parent_version,
					data=json.dumps(op.ops))
				c.save()
				doc.version = next_version
				doc.save()
				saved = True

		if saved:
			event = 'id: {}\nevent: change\ndata: {}\n\n'.format(
				c.version, json.dumps(c.export()))
			publish(
				gchannel,
				HttpStreamFormat(event),
				id=str(c.version),
				prev_id=str(c.version - 1))

		return JsonResponse({'version': c.version})
	else:
		return HttpResponseNotAllowed(['GET', 'POST'])
示例#25
0
def publish_board(board):
	players = Player.get_top_for_board(board, limit=5)
	publish(str(board.id), HttpStreamFormat('event: update\ndata: %s\n\n' % _board_json(board, players, pretty=False)))