Skip to content

Commit

Permalink
Merge pull request #2 from holaplex/espi/upload-files
Browse files Browse the repository at this point in the history
Upload files to w3.storage using web3up
  • Loading branch information
kespinola authored Oct 5, 2023
2 parents ec819aa + 3dbe8c8 commit 03763ce
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ yarn-error.log*
.pnpm-debug.log*

# local env files
.env
.env*.local

# vercel
Expand Down
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
# HUB Uploads
# HUB Upload API

A simple REST wrapper for web3up used as a shared uploads service within HUB.
This is the Upload API for HUB. It allows users to upload files to the server.

## Getting started
## Setup

```
npm i
npm run start
```
To setup the server, follow these steps:

1. Install the dependencies by running `npm install`
2. Set the environment variables `WEB3_UP_KEY`, `WEB3_UP_PROOF`, and `WEB3_UP_GATEWAY`. Note that `WEB3_UP_GATEWAY` should be an IPFS compatible gateway for retrieving assets over HTTP.
3. Start the server by running `npm start`

## Routes

The available routes are:

- POST /uploads: Upload a file. This route consumes multipart/form-data and returns the URI and CID of the uploaded file.

## Swagger Documentation

The Swagger documentation for the API is available at /documentation.

## Error Handling

If there is a validation error in the request, the server will respond with a 400 status code and the validation error.

## File Upload

The server uses the `fastify-multipart` plugin to handle file uploads. The server is configured to accept a maximum of 1 file field and 0 non-file fields.
58 changes: 50 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hub-uploads",
"version": "1.0.0",
"version": "0.1.0",
"description": "HUB file uploads services wrapper for web3 up.",
"main": "server.js",
"scripts": {
Expand All @@ -11,7 +11,11 @@
"author": "",
"license": "ISC",
"dependencies": {
"@fastify/env": "^4.2.0",
"@fastify/error": "^3.4.0",
"@fastify/multipart": "^8.0.0",
"@fastify/swagger": "^8.11.0",
"@fastify/swagger-ui": "^1.10.0",
"@ipld/car": "^5.2.4",
"@ucanto/principal": "^8.1.0",
"@web3-storage/w3up-client": "^8.0.3",
Expand Down
154 changes: 142 additions & 12 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,161 @@
import Fastify from "fastify";
import MultiPart from "@fastify/multipart";
import { Signer } from "@ucanto/principal/ed25519";
import fastifyMultiPart from "@fastify/multipart";
import fastifySwagger from "@fastify/swagger";
import fastifyEnv from "@fastify/env";
import fastifySwaggerUi from "@fastify/swagger-ui";

import { w3 } from "./web3.js";
import createError from "@fastify/error";

const UploadError = createError(
"UPLOAD_ERROR",
"The upload was not successful"
);

// Initialize Fastify with logging enabled
const fastify = Fastify({
logger: true,
});

fastify.register(MultiPart);
// Register environment variables
await fastify.register(fastifyEnv, {
dotenv: true,
schema: {
type: "object",
required: ["WEB3_UP_PROOF", "WEB3_UP_KEY", "WEB3_UP_GATEWAY"],
properties: {
WEB3_UP_PROOF: {
type: "string",
},
WEB3_UP_KEY: {
type: "string",
},
WEB3_UP_GATEWAY: {
type: "string",
},
PORT: {
type: "number",
default: 3000,
},
},
},
});

// Register multipart plugin with limits
await fastify.register(fastifyMultiPart, {
limits: {
fields: 0, // Max number of non-file fields
files: 1, // Max number of file fields
},
});

await fastify.register(fastifySwagger, {
exposeRoute: true,
swagger: {
info: {
title: "HUB Upload API",
description: "Upload API for HUB",
version: "0.1.0",
},
externalDocs: {
url: "https://docs.holaplex.com",
description: "HUB documentation",
},
host: "localhost:3000",
schemes: ["http"],
consumes: ["application/json"],
produces: ["application/json"],
tags: [],
securityDefinitions: {
apiKey: {
type: "apiKey",
name: "Authorization",
in: "header",
},
},
},
});

await fastify.register(fastifySwaggerUi, {
routePrefix: "/documentation",
initOAuth: {},
uiConfig: {
docExpansion: "full",
deepLinking: false,
},
uiHooks: {
onRequest: function (request, reply, next) {
next();
},
preHandler: function (request, reply, next) {
next();
},
},
staticCSP: true,
transformStaticCSP: (header) => header,
});

// Initialize uploader with environment variables
const uploader = await w3(
fastify.config.WEB3_UP_KEY,
fastify.config.WEB3_UP_PROOF,
fastify.config.WEB3_UP_GATEWAY
);

// Health check endpoint
fastify.get("/health", async function handler(request, reply) {
reply.send({ status: "ok" });
});

// Declare a route
fastify.post("/uploads", async function handler(request, reply) {
const parts = req.files();
// Upload endpoint
fastify.post(
"/uploads",
{
schema: {
description: "Upload a file",
tags: ["file"],
consumes: ["multipart/form-data"],
response: {
200: {
description: "File uploaded successfully",
type: "object",
properties: {
uri: { type: "string" },
cid: { type: "string" },
},
},
},
},
},
async function handler(request, reply) {
if (request.validationError) {
reply.status(400).send(request.validationError);
return;
}

for await (const part of parts) {
}
try {
// Get file from request and convert to buffer
const data = await request.file();
const buffer = await data.toBuffer();
// Upload file and get results
const results = await uploader.uploadFile(buffer);

reply.send();
});
// Send results as response
reply.send(results);
} catch {
// Send upload error as response if any error occurs
reply.send(new UploadError());
}
}
);

// Run the server!
// Start the server
try {
await fastify.listen({ port: 3000, host: "0.0.0.0" });
await fastify.ready();
fastify.swagger();
await fastify.listen({ port: fastify.config.PORT, bind: "0.0.0.0" });
} catch (err) {
// Log error and exit process if server fails to start
fastify.log.error(err);
process.exit(1);
}
Loading

0 comments on commit 03763ce

Please sign in to comment.