163 lines
3.7 KiB
Markdown
163 lines
3.7 KiB
Markdown
# Kosmi Image Upload Protocol
|
|
|
|
## Summary
|
|
|
|
Kosmi uses a **simple HTTP POST** to upload images, **NOT the WebSocket**. Images are uploaded to a dedicated CDN endpoint.
|
|
|
|
## Upload Endpoint
|
|
|
|
```
|
|
POST https://img.kosmi.io/
|
|
```
|
|
|
|
## Request Details
|
|
|
|
### Method
|
|
`POST`
|
|
|
|
### Headers
|
|
```
|
|
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary...
|
|
Origin: https://app.kosmi.io
|
|
Referer: https://app.kosmi.io/
|
|
```
|
|
|
|
**Important:** No authentication required! The endpoint accepts anonymous uploads.
|
|
|
|
### Request Body
|
|
Standard `multipart/form-data` with a single field:
|
|
|
|
```
|
|
------WebKitFormBoundary...
|
|
Content-Disposition: form-data; name="file"; filename="blurt.jpg"
|
|
Content-Type: image/jpeg
|
|
|
|
[binary image data]
|
|
------WebKitFormBoundary...--
|
|
```
|
|
|
|
### CORS
|
|
The endpoint has CORS enabled for `https://app.kosmi.io`:
|
|
```
|
|
Access-Control-Allow-Origin: https://app.kosmi.io
|
|
```
|
|
|
|
## Response
|
|
|
|
### Status
|
|
`200 OK`
|
|
|
|
### Headers
|
|
```
|
|
Content-Type: application/json
|
|
Access-Control-Allow-Origin: https://app.kosmi.io
|
|
```
|
|
|
|
### Response Body (CONFIRMED)
|
|
```json
|
|
{
|
|
"filename": "8d580b3a-905d-4bc9-909b-ccc6743edbdc.webp"
|
|
}
|
|
```
|
|
|
|
**Note:** The response contains only the filename, not the full URL. The full URL must be constructed as:
|
|
```
|
|
https://img.kosmi.io/{filename}
|
|
```
|
|
|
|
Example:
|
|
```json
|
|
{
|
|
"filename": "3460a8e1-fe19-4371-a735-64078e9923a4.webp"
|
|
}
|
|
```
|
|
→ Full URL: `https://img.kosmi.io/3460a8e1-fe19-4371-a735-64078e9923a4.webp`
|
|
|
|
## Implementation Notes
|
|
|
|
### For Go Client
|
|
|
|
1. **No authentication needed** - This is a public upload endpoint
|
|
2. **Use standard multipart/form-data** - Go's `mime/multipart` package
|
|
3. **Set CORS headers**:
|
|
- `Origin: https://app.kosmi.io`
|
|
- `Referer: https://app.kosmi.io/`
|
|
4. **Parse JSON response** to get the image URL
|
|
5. **Send the URL to Kosmi chat** via the existing WebSocket `sendMessage` mutation
|
|
|
|
### Workflow
|
|
|
|
1. Generate room code PNG image (already implemented in `roomcode_image.go`)
|
|
2. Upload PNG to `https://img.kosmi.io/` via HTTP POST
|
|
3. Parse response to get image URL
|
|
4. Send message to Kosmi chat with the image URL
|
|
5. Kosmi will automatically display the image as a thumbnail
|
|
|
|
### Security Considerations
|
|
|
|
- The endpoint is public (no auth required)
|
|
- Files are likely rate-limited or size-limited
|
|
- Images are served from `img.kosmi.io` CDN
|
|
- The upload is CORS-protected (only works from `app.kosmi.io` origin)
|
|
|
|
## Example Implementation (Pseudocode)
|
|
|
|
```go
|
|
func UploadImageToKosmi(imageData []byte, filename string) (string, error) {
|
|
// Create multipart form
|
|
body := &bytes.Buffer{}
|
|
writer := multipart.NewWriter(body)
|
|
|
|
// Add file field
|
|
part, err := writer.CreateFormFile("file", filename)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
part.Write(imageData)
|
|
writer.Close()
|
|
|
|
// Create request
|
|
req, err := http.NewRequest("POST", "https://img.kosmi.io/", body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Set headers
|
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
|
req.Header.Set("Origin", "https://app.kosmi.io")
|
|
req.Header.Set("Referer", "https://app.kosmi.io/")
|
|
|
|
// Send request
|
|
client := &http.Client{}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Parse response
|
|
var result struct {
|
|
URL string `json:"url"`
|
|
}
|
|
json.NewDecoder(resp.Body).Decode(&result)
|
|
|
|
return result.URL, nil
|
|
}
|
|
```
|
|
|
|
## Testing
|
|
|
|
To test the upload, we can:
|
|
1. Generate a test room code image
|
|
2. Upload it to `https://img.kosmi.io/`
|
|
3. Verify we get a URL back
|
|
4. Send the URL to Kosmi chat
|
|
5. Verify the image displays as a thumbnail
|
|
|
|
## References
|
|
|
|
- HAR capture: `image_upload_HAR-sanitized.har` (lines 3821-4110)
|
|
- Upload request: Line 3910-4018
|
|
- Upload response: Line 4019-4092
|
|
|