The extensions-core
module is one of Canva's Java SDKs for developing server-side extensions. It streamlines the development process and helps you avoid common pitfalls, such as misspelled field names and signature verification issues.
This module contains:
- A
Signer
utility for generating request signatures. - Plain Old Java Objects (POJOs) with JSON marshalling for API requests, responses, and models.
- Classes for implementing common functionality, such as request validation.
Usage
-
Download the module via Maven Central: search.maven.org/artifact/com.canva/extensions-core
-
Import the relevant components:
import com.canva.extensions.content.model.*;java
Requests and responses
This snippet demonstrates how to serialize and deserialize the request and response objects for the /content/resources/find
endpoint:
import com.canva.extensions.content.model.*;import com.fasterxml.jackson.databind.ObjectMapper;public class Example {private static final ObjectMapper objectMapper = new ObjectMapper();public static String handleFindResourcesRequest(String jsonBody) {// Deserialize a FindResourcesRequest from the JSON body of the HTTP request.var request = objectMapper.readValue(jsonBody, FindResourcesRequest.class);// Serialize the FindResourcesResponse.var resources = List.<Resource>of();var findResourcesResponse = new FindResourcesSuccessResponse(resources, null);return objectMapper.writeValueAsString(findResourcesResponse);}}
Models
This snippet demonstrates how to use a Resource
object to create an "IMAGE"
resource for a content extension:
import java.util.List;import com.canva.extensions.content.model.*;import com.fasterxml.jackson.databind.ObjectMapper;public class Example {private static final ObjectMapper objectMapper = new ObjectMapper();public static String handleFindResourcesRequest(String jsonBody) {// Deserialize a FindResourcesRequest from the JSON body of the HTTP request.var request = objectMapper.readValue(jsonBody, FindResourcesRequest.class);// Handle the request - return a list of Resource objects satisfying the request.var imageThumbnail = new Thumbnail("picsum.photos/id/237/200", 800, 600);var imageResource = new Resource("imageId", "An Image", ResourceType.IMAGE, "image/jpeg",imageThumbnail, "https://url.to/image.png");var resources = List.of(imageResource);// Serialize the FindResourcesResponse.var findResourcesResponse = new FindResourcesSuccessResponse(resources, "aContinuationToken");return objectMapper.writeValueAsString(findResourcesResponse);}}
Signature verification
If your app has signature verification check enabled, you must verify the signatures and timestamps of all HTTP requests. To simplify this process, the extensions-core
module includes a Signer
class for generating request signatures.
This snippet demonstrates how to use the Signer
class with the Spark framework:
import com.canva.extensions.util.Signer;import java.util.List;import static spark.Spark.post;public class Example {// Instantiated here for illustrative purposes. Ideally, provide via the constructor as a singleton.private static final Signer signer = new Signer("clientSecret");public static void main(String[] args) {post("/content/resources/find", (request, response) -> {var signatures = List.of(request.headers("X-Canva-Signatures").split(","));var sentAtSeconds = Long.parseLong(request.headers("X-Canva-Timestamp"));var path = "/content/resources/find";var signature = signer.signRequest(sentAtSeconds, path, request.body());if (!signatures.contains(signature)) {response.status(401);return response;}var receivedAtSeconds = System.currentTimeMillis() / 1000;var leniencyInSeconds = 5 * 60; // 5 minutesif (receivedAtSeconds - sentAtSeconds > leniencyInSeconds) {response.status(401);return response;}// If the above has passed, then the request is valid and can be handled safely.// Here we'd handle the findResources request and return a FindResources(Success|Error)Response.return response;});}}