@POST @ApiOperation(value = "Copy events directly to database", request = EventList.class, response = Integer.class) @Path("/copy") public void copyEvents(RakamHttpRequest request) { bulkEvents(request, false); }
@POST @ApiOperation(value = "Collect bulk events from remote", request = BulkEventRemote.class, response = Integer.class) @ApiResponses(value = {@ApiResponse(code = 409, message = PARTIAL_ERROR_MESSAGE, response = int[].class)}) @Path("/bulk/remote") public void bulkEventsRemote(RakamHttpRequest request) { bulkEventsRemote(request, true); }
public static void setBrowser(HttpRequest request, HttpResponse response) { response.headers().set(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); if (request.headers().contains(ORIGIN)) { response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, request.headers().get(ORIGIN)); } String headerList = getHeaderList(request.headers().iterator()); if (headerList != null) { response.headers().set(ACCESS_CONTROL_EXPOSE_HEADERS, headerList); } }
cookiesFuture = mapEvent(eventMappers, mapper -> mapper.mapAsync(event, new HttpRequestParams(request), getRemoteAddress(socketAddress), response.trailingHeaders())) .thenCombine(eventStore.storeAsync(event), (cookies, aVoid) -> cookies); } catch (JsonMappingException e) { String message = e.getCause() != null ? e.getCause().getMessage() : e.getMessage(); returnError(request, "JSON couldn't parsed: " + message, BAD_REQUEST); return; } catch (IOException e) { returnError(request, "JSON couldn't parsed: " + e.getMessage(), BAD_REQUEST); return; } catch (RakamException e) { LogUtil.logException(request, e); returnError(request, e.getMessage(), e.getStatusCode()); return; } catch (HttpRequestException e) { returnError(request, e.getMessage(), e.getStatusCode()); return; } catch (IllegalArgumentException e) { LogUtil.logException(request, e); returnError(request, e.getMessage(), BAD_REQUEST); return; } catch (Exception e) { LOGGER.error(e, "Error while collecting event"); returnError(request, "An error occurred", INTERNAL_SERVER_ERROR); return; String headerList = getHeaderList(response.headers().iterator()); if (headerList != null) {
setBrowser(request, response); response.headers().add(SET_COOKIE, STRICT.encode(cookies)); String headerList = getHeaderList(response.headers().iterator()); if (headerList != null) { response.headers().set(ACCESS_CONTROL_EXPOSE_HEADERS, headerList); } catch (RakamException e) { LogUtil.logException(request, e); EventCollectionHttpService.returnError(request, e.getMessage(), e.getStatusCode()); } catch (HttpRequestException e) { EventCollectionHttpService.returnError(request, e.getMessage(), e.getStatusCode()); } catch (Throwable t) { LOGGER.error(t); EventCollectionHttpService.returnError(request, "An error occurred", INTERNAL_SERVER_ERROR);
Event event = jsonMapper.convertValue(objectNode, Event.class); cookiesFuture = mapEvent(eventMappers, (mapper) -> mapper.mapAsync(event, new HttpRequestParams(request), getRemoteAddress(socketAddress), response.trailingHeaders())); cookiesFuture.thenAccept(v -> eventStore.store(event)); } catch (RakamException e) {
public void bulkEvents(RakamHttpRequest request, boolean mapEvents) { storeEventsSync(request, buff -> { String contentType = request.headers().get(CONTENT_TYPE); String apiKey; try { apiKey = getParam(request.params(), MASTER_KEY.getKey()); } catch (Exception e) { apiKey = request.headers().get(MASTER_KEY.getKey()); String collection = getParam(request.params(), "collection"); String apiKey = getParam(request.params(), MASTER_KEY.getKey()); String project = apiKeyService.getProjectOfApiKey(apiKey, MASTER_KEY); String collection = getParam(request.params(), "collection"); String apiKey = getParam(request.params(), MASTER_KEY.getKey()); String project = apiKeyService.getProjectOfApiKey(apiKey, MASTER_KEY); String collection = getParam(request.params(), "collection");
public static void returnError(RakamHttpRequest request, String msg, HttpResponseStatus status) { ByteBuf byteBuf = Unpooled.wrappedBuffer(JsonHelper.encodeAsBytes(errorMessage(msg, status))); DefaultFullHttpResponse errResponse = new DefaultFullHttpResponse(HTTP_1_1, status, byteBuf); setBrowser(request, errResponse); request.response(errResponse).end(); }
public void storeEventsSync(RakamHttpRequest request, ThrowableFunction mapper, BiFunction<List<Event>, HttpHeaders, FullHttpResponse> responseFunction, boolean mapEvents) { storeEvents(request, mapper, (events, entries) -> completedFuture(responseFunction.apply(events, entries)), mapEvents); }
@IgnoreApi @POST @ApiOperation(value = "Collect event via Pixel", request = Event.class) @Path("/pixel") public void pixelPost(RakamHttpRequest request) { pixel(request); }
public void store(String jsonRaw) throws IOException { if (jsonEventDeserializer == null) { throw new RakamException("Event store is not supported.", BAD_REQUEST); } JsonParser jp = JsonHelper.getMapper().getFactory().createParser(jsonRaw); JsonToken t = jp.nextToken(); if (t != JsonToken.START_ARRAY) { throw new RakamException("The script didn't return an array", BAD_REQUEST); } t = jp.nextToken(); List<Event> list = new ArrayList<>(); for (; t == START_OBJECT; t = jp.nextToken()) { list.add(jsonEventDeserializer.deserializeWithProject(jp, project, Event.EventContext.empty(), true)); } EventCollectionHttpService.mapEvent(eventMapperSet, eventMapper -> eventMapper.mapAsync(new EventList(Event.EventContext.empty(), list), EMPTY_PARAMS, localhost, HttpHeaders.EMPTY_HEADERS)); int[] ints = eventStore.storeBatch(list); if (ints.length > 0) { logger.error(format("Failed to save events: %s", Arrays.stream(ints).boxed().map(i -> i + "").collect(Collectors.joining(", ")))); } } }
testEventsProxy, new EventCollectionHttpService.HttpRequestParams(request), EventCollectionHttpService.getRemoteAddress(request.getRemoteAddress()), responseHeaders, new JSSQLExecutor(context.project),
InetAddress remoteAddress = getRemoteAddress(request.getRemoteAddress()); entries = mapEvent(eventMappers, (m) -> m.mapAsync(events, new HttpRequestParams(request), remoteAddress, responseHeaders)); } else { returnError(request, "JSON couldn't parsed: " + e.getOriginalMessage(), BAD_REQUEST); return; } catch (IOException e) { returnError(request, "JSON couldn't parsed: " + e.getMessage(), BAD_REQUEST); return; } catch (RakamException e) { LogUtil.logException(request, e); returnError(request, e.getMessage(), e.getStatusCode()); return; } catch (HttpRequestException e) { returnError(request, e.getMessage(), e.getStatusCode()); return; } catch (IllegalArgumentException e) { LogUtil.logException(request, e); returnError(request, e.getMessage(), BAD_REQUEST); return; } catch (Throwable e) { LOGGER.error(e, "Error while collecting event"); returnError(request, "An error occurred", INTERNAL_SERVER_ERROR); return; String headerList = getHeaderList(responseHeaders.iterator());
@ApiOperation(value = "Batch operation on a single user properties", request = SingleUserBatchOperationRequest.class, response = Integer.class, authorizations = {@Authorization(value = "write_key")}) @ApiResponses(value = {@ApiResponse(code = 404, message = "User does not exist.")}) @Path("/batch") @JsonRequest public void batchSingleUserOperations(RakamHttpRequest request) { request.bodyHandler(s -> { SingleUserBatchOperationRequest req; try { req = JsonHelper.read(s, SingleUserBatchOperationRequest.class); } catch (Exception e) { returnError(request, e.getMessage(), BAD_REQUEST); return; } String project = apiKeyService.getProjectOfApiKey(req.api.apiKey, WRITE_KEY); InetAddress socketAddress = ((InetSocketAddress) request.context().channel() .remoteAddress()).getAddress(); DefaultFullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, wrappedBuffer(OK_MESSAGE)); List<Cookie> cookies = mapEvent(mapper -> mapper.map(project, req.data, new HttpRequestParams(request), socketAddress)); service.batch(project, req.data); setBrowser(request, response); if (cookies != null && !cookies.isEmpty()) { response.headers().add(SET_COOKIE, STRICT.encode(cookies)); } request.response(response).end(); }); }
@Path("/batch") public void batchEvents(RakamHttpRequest request) { storeEvents(request, buff -> { if (buff.available() > 500000) { throw new RakamException("The body is too big, use /bulk endpoint.", REQUEST_ENTITY_TOO_LARGE);
@JsonRequest @ApiOperation(value = "Merge user with anonymous id", authorizations = @Authorization(value = "write_key")) @ApiResponses(value = {@ApiResponse(code = 404, message = "User does not exist.")}) @Path("/merge") @IgnoreApi @AllowCookie public void mergeUser(RakamHttpRequest request, @BodyParam MergeRequest mergeRequest) { // TODO: what if a user sends real user ids instead of its previous anonymous id? if (!config.getEnableUserMapping()) { throw new RakamException("The feature is not supported", PRECONDITION_FAILED); } Object anonymousId = mergeRequest.anonymousId; DefaultFullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, wrappedBuffer(OK_MESSAGE)); setBrowser(request, response); if (anonymousId == null) { throw new RakamException("Anonymous id is required", BAD_REQUEST); } String project = apiKeyService.getProjectOfApiKey(mergeRequest.api.apiKey, WRITE_KEY); service.merge(project, mergeRequest.id, anonymousId, Instant.ofEpochMilli(mergeRequest.createdAt), Instant.ofEpochMilli(mergeRequest.mergedAt)); request.response(response).end(); }
@POST @ApiOperation(value = "Collect Bulk events", request = EventList.class, response = SuccessMessage.class, notes = "Bulk API requires master_key as api key and built for importing the data without any rate limiting unlike event/batch" + "This endpoint accepts application/json and the data format is same as event/batch. Additionally it supports application/x-rawjson for JSON dump data, application/x-ndjson for newline delimited JSON, application/avro for AVRO and text/csv for CSV formats. You need need to set 'collection' and 'master_key' query parameters if the content-type is not application/json.") @Path("/bulk") public void bulkEvents(RakamHttpRequest request) { bulkEvents(request, true); }
@JsonRequest @ApiOperation(value = "Set user properties once", request = User.class, response = Integer.class) @ApiResponses(value = {@ApiResponse(code = 404, message = "User does not exist.")}) @Path("/set_properties_once") public void setPropertiesOnce(RakamHttpRequest request) { request.bodyHandler(s -> { User req; try { req = JsonHelper.readSafe(s, User.class); } catch (IOException e) { returnError(request, e.getMessage(), BAD_REQUEST); return; } String project = apiKeyService.getProjectOfApiKey(req.api.apiKey, WRITE_KEY); DefaultFullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, wrappedBuffer(OK_MESSAGE)); response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, request.headers().get(ORIGIN)); List<Cookie> cookies = mapProperties(project, req, request); if (cookies != null) { response.headers().add(SET_COOKIE, STRICT.encode(cookies)); } String headerList = getHeaderList(response.headers().iterator()); if (headerList != null) { response.headers().set(ACCESS_CONTROL_EXPOSE_HEADERS, headerList); } // TODO: we may cache these values and reduce the db hit. service.setUserPropertiesOnce(project, req.id, req.properties); request.response(OK_MESSAGE).end(); }); }
setBrowser(request, response);