Skip to content

fix(cors): add proper CORS configuration for content routes#3192

Closed
luke1879012 wants to merge 1 commit intocloudreve:masterfrom
luke1879012:master
Closed

fix(cors): add proper CORS configuration for content routes#3192
luke1879012 wants to merge 1 commit intocloudreve:masterfrom
luke1879012:master

Conversation

@luke1879012
Copy link
Copy Markdown

English Version
Title: Fix incomplete CORS configuration for /file/content endpoint
Description
Problem:
When accessing video or file content via the /api/v4/file/content endpoint from a cross-origin context (e.g., embedded in Obsidian notes or other third-party applications), the browser's preflight (OPTIONS) request fails. This is because the CORS middleware for this endpoint only sets AllowOrigins: ["*"] but lacks other essential CORS headers such as AllowMethods, AllowHeaders, and ExposeHeaders.

Example Scenario:

When embedding Cloudreve-hosted videos in Obsidian notes:

<!-- ❌ FAILS: Cross-origin request via HTTPS domain -->
<video width="100%" controls crossorigin="anonymous">
  <source src="https://cloud.example.com/api/v4/file/content/xxx/0/video.mp4?sign=..." type="video/mp4">
</video>
<!-- ✅ WORKS: Direct IP access (no cross-origin restrictions) -->
<video width="100%" controls>
  <source src="http://192.168.1.100:5212/api/v4/file/content/xxx/0/video.mp4?sign=..." type="video/mp4">
</video>
The first example fails because the browser sends a preflight OPTIONS request, which doesn't receive proper CORS headers. The second example works because it's either same-origin or the browser doesn't enforce CORS for direct IP access in certain contexts.

Root Cause:
The contentCors configuration in
routers/router.go
(around line 601) was incomplete:

contentCors := cors.New(cors.Config{
    AllowOrigins: []string{"*"},
})

Solution:
Added complete CORS configuration including:

  • AllowMethods: GET, HEAD, OPTIONS
  • AllowHeaders: Range, If-Range, Authorization, Content-Type
  • ExposeHeaders: Content-Range, Accept-Ranges, Content-Length, Content-Disposition
  • After this fix, both examples work correctly.

中文版本
标题:修复 /file/content 端点的 CORS 配置不完整问题
描述
问题现象:
当从跨域环境(如嵌入在 Obsidian 笔记或其他第三方应用中)访问 /api/v4/file/content 端点的视频或文件内容时,浏览器的预检请求(OPTIONS)会失败。这是因为该端点的 CORS 中间件只设置了 AllowOrigins: ["*"],但缺少其他必要的 CORS 头。

问题复现示例:

在 Obsidian 笔记中嵌入 Cloudreve 托管的视频时:

<!-- ❌ 失败:通过 HTTPS 域名的跨域请求 -->
<video width="100%" controls crossorigin="anonymous">
  <source src="https://cloud.example.com/api/v4/file/content/xxx/0/video.mp4?sign=..." type="video/mp4">
</video>
<!-- ✅ 成功:直接 IP 访问(无跨域限制) -->
<video width="100%" controls>
  <source src="http://192.168.1.100:5212/api/v4/file/content/xxx/0/video.mp4?sign=..." type="video/mp4">
</video>

第一个示例失败是因为浏览器发送了预检 OPTIONS 请求,但没有收到正确的 CORS 响应头。第二个示例能正常工作是因为直接 IP 访问在某些情况下不受跨域限制。

根本原因:
routers/router.go
文件(约第 601 行)中的 contentCors 配置不完整:

contentCors := cors.New(cors.Config{
    AllowOrigins: []string{"*"},
})

解决方案:
添加完整的 CORS 配置,包括:

  • AllowMethods:GET、HEAD、OPTIONS
  • AllowHeaders:Range、If-Range、Authorization、Content-Type
  • ExposeHeaders:Content-Range、Accept-Ranges、Content-Length、Content-Disposition
    修复后,以上两种方式均可正常播放视频。

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jan 14, 2026

CLA assistant check
All committers have signed the CLA.

AllowOrigins: []string{"*"},
AllowMethods: []string{"GET", "HEAD", "OPTIONS"},
AllowHeaders: []string{"Range", "If-Range", "Authorization", "Content-Type"},
ExposeHeaders: []string{"Content-Range", "Accept-Ranges", "Content-Length", "Content-Disposition"},
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add more exposed headers: Content-Disposition, ETag

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

English:
When can it be repaired? Although I can currently access it through IP, the data is inconsistent, which makes my OCD very uncomfortable.
中文:
请问什么时候可以修复呢?虽然目前可以用ip访问,但是数据不一致,导致我的强迫症很难受。

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the setting item from conf.ini rather then hard coding?

Copy link
Copy Markdown
Member

@YUDONGLING YUDONGLING Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

English: When can it be repaired? Although I can currently access it through IP, the data is inconsistent, which makes my OCD very uncomfortable. 中文: 请问什么时候可以修复呢?虽然目前可以用ip访问,但是数据不一致,导致我的强迫症很难受。

As a temporary fix, if you are using a reverse proxy/CDN for Cloudreve, you may uodate their configuration to add these CORS headers. Fix in 4.12.0.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the setting item from conf.ini rather then hard coding?

you are right

@HFO4 HFO4 closed this in 864332f Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants