Skip to content

Commit

Permalink
feat: 所有平台迁移到官方的正向代理
Browse files Browse the repository at this point in the history
  • Loading branch information
terwer committed Aug 13, 2023
1 parent 0af57ce commit c4de13f
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 196 deletions.
14 changes: 4 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ In later releases, the release configuration will only be backward compatible to

## Recent critical updates and bug fixes

- All platforms migrated to official forward proxy
- Support replacing picture bed image links with Picgo plugin
- Fixed the issue that the release preview of the authorization code mode was invalidated
- Support publishing to Zhihu
Expand All @@ -30,21 +31,14 @@ In later releases, the release configuration will only be backward compatible to
This plugin supports almost all devices and platforms of Siyuan Note, and the specific compatibility is as follows:

- [X] Siyuan Note Client (zero configuration) <sup>is highly recommended</sup>
- [X] Servo environment (cross-domain request proxy needs to be set)
- [X] Servo environment (Zero configuration, cross-domain request proxy built-in)
- [X] CentSource Note Browser Servo
- [X] Siyuan Note Client Servo
- [X] Siyuan Notemaker mobile servo
- [X] Siyuan Note docker version (need to set up cross-domain request proxy)
- [X] Siyuan Note docker version (Zero configuration, cross-domain request proxy built-in)

**Note: If it is a LAN servo, you need to deploy the cross-domain proxy on the LAN.**
🎉 **All platforms have been migrated to the official forward proxy, achieving zero user configuration and supporting cross-domain request proxies by default 🎉**

**Set up the method, clone https://github.com/terwer/node-metaweblog-api-adaptor then `pnpm install & pnpm dev`, after startup the proxy address is https://<local-IP>:3000/api/middleware .**

**If the Internet needs to be deployed on the Internet, the cross-domain request proxy of the Internet can also be used directly: https://api.terwer.space/api/middleware**

**It may be migrated to the official forward proxy to achieve zero configuration in the future, but for now you must set it yourself, you can follow the progress here.**

- Progress 1: The Yuque and Notion platforms have used the built-in forward proxy and do not need to be configured.

## Platform List

Expand Down
15 changes: 4 additions & 11 deletions README_zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

## 最近的关键更新与 Bug 修复

- 所有平台迁移到官方的正向代理
- 支持使用Picgo插件的情况下替换图床图片链接
- 修复授权码模式发布预览失效问题
- 支持发布到知乎
Expand All @@ -28,21 +29,13 @@
本插件支持思源笔记几乎所有设备和平台,具体兼容情况如下:

- [X] 思源笔记客户端(零配置)<sup>强烈推荐</sup>
- [X] 伺服环境(需要设置跨域请求代理
- [X] 伺服环境(零配置,跨域请求代理已内置
- [X] 思源笔记浏览器伺服
- [X] 思源笔记客户端伺服
- [X] 思源笔记客移动端伺服
- [X] 思源笔记docker版(需要设置跨域请求代理
- [X] 思源笔记docker版(零配置,跨域请求代理已内置

**注意:如果是局域网伺服,需要在局域网自行部署跨域代理。**

**设置方法,clone https://github.com/terwer/node-metaweblog-api-adaptor 然后 `pnpm install && pnpm dev`,启动之后代理地址为:https://<局域网IP>:3000/api/middleware 。**

**如果是外网需要部署在外网,外网的跨域请求代理也可以直接使用:https://api.terwer.space/api/middleware**

**后续可能会迁移到官方的正向代理实现零配置,但是目前还是必须要自己设置,可在这里关注进展。**

- 进度1:语雀、Notion平台已使用内置正向代理,无需配置。
**🎉 所有平台均已迁移到官方的正向代理,实现了用户零配置,默认支持跨域请求代理 🎉**

## 平台列表

Expand Down
85 changes: 5 additions & 80 deletions src/adaptors/api/base/baseBlogApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,9 @@
*/

import { BlogApi, BlogConfig, Post } from "zhi-blog-api"
import { SiyuanKernelApi } from "zhi-siyuan-api"
import { CommonFetchClient } from "zhi-fetch-middleware"
import { AppInstance } from "~/src/appInstance.ts"
import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts"
import { useSiyuanApi } from "~/src/composables/useSiyuanApi.ts"
import { JsonUtil, ObjectUtil, StrUtil } from "zhi-common"
import { isDev } from "~/src/utils/constants.ts"
import { useProxy } from "~/src/composables/useProxy.ts"

/**
* API授权统一封装基类
Expand All @@ -42,9 +38,7 @@ import { isDev } from "~/src/utils/constants.ts"
export class BaseBlogApi extends BlogApi {
protected logger: ILogger
protected cfg: BlogConfig
private readonly kernelApi: SiyuanKernelApi
private readonly commonFetchClient: CommonFetchClient
private readonly useSiyuanProxy: boolean
protected readonly proxyFetch: any

/**
* 初始化API授权适配器
Expand All @@ -57,11 +51,9 @@ export class BaseBlogApi extends BlogApi {

this.cfg = cfg
this.logger = createAppLogger("base-blog-api")
this.commonFetchClient = new CommonFetchClient(appInstance, cfg.apiUrl, cfg.middlewareUrl, isDev)

const { kernelApi, isUseSiyuanProxy } = useSiyuanApi()
this.kernelApi = kernelApi
this.useSiyuanProxy = isUseSiyuanProxy()
const { proxyFetch } = useProxy(cfg.middlewareUrl)
this.proxyFetch = proxyFetch
}

public async preEditPost(post: Post, id?: string, publishCfg?: any): Promise<Post> {
Expand All @@ -72,78 +64,11 @@ export class BaseBlogApi extends BlogApi {
// ================
// private methods
// ================
protected async readFileToBlob(url: string) {
public async readFileToBlob(url: string) {
const response = await this.proxyFetch(url, [], {}, "GET", "image/jpeg")
const body = response.body
const blobData = new Blob([body], { type: response.contentType })
this.logger.debug("blobData =>", blobData)
return blobData
}

/**
* 网页授权通用的请求代理
*
* @param url - url
* @param headers - headers,默认是[]
* @param params - 参数,默认是 {}
* @param method - 方法,默认是GET
* @param contentType - 类型,默认是 application/json
*/
protected async proxyFetch(
url: string,
headers: any[] = [],
params: any = {},
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" = "GET",
contentType: string = "application/json"
): Promise<any> {
let body: any
if (typeof params === "string" && !StrUtil.isEmptyString(params)) {
body = params
} else if (typeof params === "object" && !ObjectUtil.isEmptyObject(params)) {
body = params
}

if (this.useSiyuanProxy) {
this.logger.info("using siyuan forwardProxy")
const apiUrl = `${this.cfg.apiUrl}${url}`
this.logger.info("siyuan forwardProxy url =>", apiUrl)
this.logger.info("siyuan forwardProxy fetchOptions =>", {
headers,
body,
method,
contentType,
})
const fetchResult = await this.kernelApi.forwardProxy(apiUrl, headers, body, method, contentType, 7000)
this.logger.debug("siyuan forwardProxy result=>", fetchResult)
// 后续调试可打开这个日志
// this.logger.debug("proxyFetch resText=>", resText)
if (contentType === "application/json") {
const resText = fetchResult?.body
const res = JsonUtil.safeParse<any>(resText, {} as any)
return res
} else if (contentType === "text/html") {
const resText = fetchResult?.body
return resText
} else {
return fetchResult
}
} else {
this.logger.info("using commonFetchClient")
const header = headers.length > 0 ? headers[0] : {}
let fetchOptions: any = {
method,
headers: {
...header,
},
}
if (body) {
fetchOptions.body = body
}
this.logger.info("commonFetchClient url =>", url)
this.logger.info("commonFetchClient fetchOptions =>", fetchOptions)
const res = await this.commonFetchClient.fetchCall(url, fetchOptions)
this.logger.debug("commonFetchClient res =>", res)
return res
}
}
}
11 changes: 5 additions & 6 deletions src/adaptors/api/base/metaweblog/metaweblogBlogApiAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,12 @@

import { Attachment, CategoryInfo, MediaObject, Post, PostStatusEnum, UserBlog } from "zhi-blog-api"
import { createAppLogger } from "~/src/utils/appLogger.ts"
import { CommonXmlrpcClient } from "zhi-xmlrpc-middleware"
import { MetaweblogConstants } from "~/src/adaptors/api/base/metaweblog/metaweblogConstants.ts"
import { StrUtil } from "zhi-common"
import { BrowserUtil } from "zhi-device"
import { BaseBlogApi } from "~/src/adaptors/api/base/baseBlogApi.ts"
import { MetaweblogConfig } from "~/src/adaptors/api/base/metaweblog/metaweblogConfig.ts"
import { result } from "lodash-es"
import { data } from "cheerio/lib/api/attributes"
import { useProxy } from "~/src/composables/useProxy.ts"

/**
* MetaweblogBlogApi 类继承自 BaseBlogApi 类,并为 Metaweblog API 提供了额外的功能
Expand All @@ -42,7 +40,7 @@ import { data } from "cheerio/lib/api/attributes"
* @since 0.9.0
*/
class MetaweblogBlogApiAdaptor extends BaseBlogApi {
private readonly commonXmlrpcClient: CommonXmlrpcClient
private readonly proxyXmlrpc: any

/**
* 初始化 metaweblog API 适配器
Expand All @@ -55,7 +53,8 @@ class MetaweblogBlogApiAdaptor extends BaseBlogApi {

this.cfg.blogid = "metaweblog"
this.logger = createAppLogger("metaweblog-api-adaptor")
this.commonXmlrpcClient = new CommonXmlrpcClient(appInstance, cfg.apiUrl)
const { proxyXmlrpc } = useProxy(cfg.middlewareUrl)
this.proxyXmlrpc = proxyXmlrpc
}

public override async getUsersBlogs(): Promise<Array<UserBlog>> {
Expand Down Expand Up @@ -230,7 +229,7 @@ class MetaweblogBlogApiAdaptor extends BaseBlogApi {
}

protected async metaweblogCall(method: string, params: any[]) {
return await this.commonXmlrpcClient.methodCall(method, params, this.cfg.middlewareUrl)
return await this.proxyXmlrpc(this.cfg.apiUrl, method, params)
}

/**
Expand Down
5 changes: 3 additions & 2 deletions src/adaptors/api/yuque/yuqueApiAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,12 +297,13 @@ class YuqueApiAdaptor extends BaseBlogApi {
}

// 打印日志
this.logger.debug("向语雀请求数据,url =>", url)
const apiUrl = `${this.cfg.apiUrl}${url}`
this.logger.debug("向语雀请求数据,apiUrl =>", apiUrl)
this.logger.debug("向语雀请求数据,params =>", params)

// 使用兼容的fetch调用并返回统一的JSON数据
const body = ObjectUtil.isEmptyObject(params) ? "" : JSON.stringify(params)
const resJson = await this.proxyFetch(url, [headers], body, method, contentType)
const resJson = await this.proxyFetch(apiUrl, [headers], body, method, contentType)
this.logger.debug("向语雀请求数据,resJson =>", resJson)

if (resJson?.status === 401) {
Expand Down
82 changes: 5 additions & 77 deletions src/adaptors/web/base/baseWebApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@
* questions.
*/
import { Attachment, ElectronCookie, MediaObject, Post, WebApi, WebConfig } from "zhi-blog-api"
import { SiyuanKernelApi } from "zhi-siyuan-api"
import { CommonFetchClient } from "zhi-fetch-middleware"
import { AppInstance } from "~/src/appInstance.ts"
import { createAppLogger, ILogger } from "~/src/utils/appLogger.ts"
import { useSiyuanApi } from "~/src/composables/useSiyuanApi.ts"
import { JsonUtil } from "zhi-common"
import { isDev } from "~/src/utils/constants.ts"
import { useProxy } from "~/src/composables/useProxy.ts"

/**
* 网页授权统一封装基类
Expand All @@ -41,9 +37,7 @@ import { isDev } from "~/src/utils/constants.ts"
class BaseWebApi extends WebApi {
protected logger: ILogger
protected cfg: WebConfig
private readonly kernelApi: SiyuanKernelApi
private readonly commonFetchClient: CommonFetchClient
private readonly useSiyuanProxy: boolean
protected readonly proxyFetch: any

/**
* 初始化网页授权 API 适配器
Expand All @@ -56,11 +50,9 @@ class BaseWebApi extends WebApi {

this.cfg = cfg
this.logger = createAppLogger("base-web-api")
this.commonFetchClient = new CommonFetchClient(appInstance, cfg.apiUrl, cfg.middlewareUrl, isDev)

const { kernelApi, isUseSiyuanProxy } = useSiyuanApi()
this.kernelApi = kernelApi
this.useSiyuanProxy = isUseSiyuanProxy()
const { proxyFetch } = useProxy(cfg.middlewareUrl)
this.proxyFetch = proxyFetch
}

// web 适配器专有
Expand Down Expand Up @@ -116,77 +108,13 @@ class BaseWebApi extends WebApi {
// ================
// private methods
// ================
protected async readFileToBlob(url: string) {
public async readFileToBlob(url: string) {
const response = await this.proxyFetch(url, [], {}, "GET", "image/jpeg")
const body = response.body
const blobData = new Blob([body], { type: response.contentType })
this.logger.debug("blobData =>", blobData)
return blobData
}

/**
* 网页授权通用的请求代理
*
* @param url - url
* @param headers - 请求头,默认取 password 作为 cookie
* @param params - 参数,默认是 {}
* @param method - 方法,默认是GET
* @param contentType - 类型,默认是 application/json
*/
protected async proxyFetch(
url: string,
headers: any[] = [],
params: any = {},
method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" = "GET",
contentType: string = "application/json"
): Promise<any> {
if (this.useSiyuanProxy) {
this.logger.info("using siyuan forwardProxy")
const fetchResult = await this.kernelApi.forwardProxy(
url,
headers.length > 0
? headers
: [
{
Cookie: this.cfg.password,
},
],
params,
method,
contentType,
7000
)
this.logger.debug("proxyFetch result=>", fetchResult)
// 后续调试可打开这个日志
// this.logger.debug("proxyFetch resText=>", resText)
if (contentType === "application/json") {
const resText = fetchResult?.body
const res = JsonUtil.safeParse<any>(resText, {} as any)
return res
} else if (contentType === "text/html") {
const resText = fetchResult?.body
return resText
} else {
return fetchResult
}
} else {
this.logger.info("using middleware proxy")
const header = headers.length > 0 ? headers[0] : {}
const fetchOptions = {
method: method,
headers: {
"Content-Type": "application/json",
Cookie: this.cfg.password,
...header,
},
}
this.logger.info("commonFetchClient from proxyFetch url =>", url)
this.logger.info("commonFetchClient from proxyFetch fetchOptions =>", fetchOptions)
const res = await this.commonFetchClient.fetchCall(url, fetchOptions)
this.logger.debug("commonFetchClient res from proxyFetch =>", res)
return res
}
}
}

export { BaseWebApi }

0 comments on commit c4de13f

Please sign in to comment.