|
@@ -2,7 +2,7 @@ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
|
|
|
|
|
|
|
const corsHeaders = {
|
|
const corsHeaders = {
|
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Origin': '*',
|
|
|
- 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-shoprenter-shop, x-shoprenter-domain',
|
|
|
|
|
|
|
+ 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-shoprenter-shop, x-shoprenter-token',
|
|
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -14,15 +14,12 @@ const corsHeaders = {
|
|
|
* but ShopRenter API requires HTTP/1.0.
|
|
* but ShopRenter API requires HTTP/1.0.
|
|
|
*
|
|
*
|
|
|
* Usage from n8n:
|
|
* Usage from n8n:
|
|
|
- * 1. Set Authorization header with Bearer token (from ShopRenter OAuth)
|
|
|
|
|
- * 2. Set X-ShopRenter-Shop header with shop name (e.g., "myshop" or "elektromosroller")
|
|
|
|
|
- * 3. (Optional) Set X-ShopRenter-Domain header:
|
|
|
|
|
- * - "shoprenter.hu" (default) - forwards to https://{shop}.shoprenter.hu
|
|
|
|
|
- * - "oauth.app.shoprenter.net" - forwards to https://oauth.app.shoprenter.net/{shop}
|
|
|
|
|
- * 4. Make requests to: /shoprenter-proxy/api/{endpoint}
|
|
|
|
|
|
|
+ * 1. Set X-ShopRenter-Token header with access token (from ShopRenter OAuth)
|
|
|
|
|
+ * - Use X-ShopRenter-Token instead of Authorization to avoid Supabase JWT validation
|
|
|
|
|
+ * 2. Set X-ShopRenter-Shop header with shop name (e.g., "elektromosroller")
|
|
|
|
|
+ * 3. Make requests to: /shoprenter-proxy/api/{endpoint}
|
|
|
*
|
|
*
|
|
|
* All request methods (GET, POST, PUT, PATCH, DELETE) are supported.
|
|
* All request methods (GET, POST, PUT, PATCH, DELETE) are supported.
|
|
|
- * All headers (except Host and X-ShopRenter-*) are forwarded transparently.
|
|
|
|
|
* Request and response bodies are proxied as-is.
|
|
* Request and response bodies are proxied as-is.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
@@ -39,7 +36,7 @@ serve(async (req) => {
|
|
|
return new Response(
|
|
return new Response(
|
|
|
JSON.stringify({
|
|
JSON.stringify({
|
|
|
error: 'Missing X-ShopRenter-Shop header',
|
|
error: 'Missing X-ShopRenter-Shop header',
|
|
|
- message: 'Please provide the shop name in the X-ShopRenter-Shop header (e.g., "myshop" or "elektromosroller")'
|
|
|
|
|
|
|
+ message: 'Please provide the shop name in the X-ShopRenter-Shop header (e.g., "elektromosroller")'
|
|
|
}),
|
|
}),
|
|
|
{
|
|
{
|
|
|
status: 400,
|
|
status: 400,
|
|
@@ -48,8 +45,20 @@ serve(async (req) => {
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Extract domain preference (defaults to shoprenter.hu)
|
|
|
|
|
- const domain = req.headers.get('X-ShopRenter-Domain') || 'shoprenter.hu'
|
|
|
|
|
|
|
+ // Extract ShopRenter token from custom header
|
|
|
|
|
+ const shopRenterToken = req.headers.get('X-ShopRenter-Token')
|
|
|
|
|
+ if (!shopRenterToken) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ error: 'Missing X-ShopRenter-Token header',
|
|
|
|
|
+ message: 'Please provide the ShopRenter access token in the X-ShopRenter-Token header'
|
|
|
|
|
+ }),
|
|
|
|
|
+ {
|
|
|
|
|
+ status: 400,
|
|
|
|
|
+ headers: { ...corsHeaders, 'Content-Type': 'application/json' }
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// Extract API endpoint from URL path
|
|
// Extract API endpoint from URL path
|
|
|
const url = new URL(req.url)
|
|
const url = new URL(req.url)
|
|
@@ -70,29 +79,30 @@ serve(async (req) => {
|
|
|
|
|
|
|
|
const apiPath = pathMatch[1]
|
|
const apiPath = pathMatch[1]
|
|
|
|
|
|
|
|
- // Construct ShopRenter API URL based on domain
|
|
|
|
|
- let shopRenterUrl: string
|
|
|
|
|
- if (domain === 'oauth.app.shoprenter.net') {
|
|
|
|
|
- // For OAuth API: https://oauth.app.shoprenter.net/{shop}{apiPath}
|
|
|
|
|
- shopRenterUrl = `https://oauth.app.shoprenter.net/${shopName}${apiPath}${url.search}`
|
|
|
|
|
- } else {
|
|
|
|
|
- // For standard API: https://{shop}.shoprenter.hu{apiPath}
|
|
|
|
|
- shopRenterUrl = `https://${shopName}.shoprenter.hu${apiPath}${url.search}`
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Construct ShopRenter API URL - always use standard .shoprenter.hu domain
|
|
|
|
|
+ const shopRenterUrl = `https://${shopName}.shoprenter.hu${apiPath}${url.search}`
|
|
|
|
|
|
|
|
console.log(`[ShopRenter Proxy] Forwarding ${req.method} request to: ${shopRenterUrl}`)
|
|
console.log(`[ShopRenter Proxy] Forwarding ${req.method} request to: ${shopRenterUrl}`)
|
|
|
|
|
|
|
|
// Prepare headers for ShopRenter API request
|
|
// Prepare headers for ShopRenter API request
|
|
|
const shopRenterHeaders = new Headers()
|
|
const shopRenterHeaders = new Headers()
|
|
|
|
|
|
|
|
- // Copy all headers from the original request except Host and custom headers
|
|
|
|
|
|
|
+ // Copy all headers from the original request except Host, Authorization, and custom headers
|
|
|
for (const [key, value] of req.headers.entries()) {
|
|
for (const [key, value] of req.headers.entries()) {
|
|
|
const lowerKey = key.toLowerCase()
|
|
const lowerKey = key.toLowerCase()
|
|
|
- if (lowerKey !== 'host' && !lowerKey.startsWith('x-shoprenter-')) {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ lowerKey !== 'host' &&
|
|
|
|
|
+ lowerKey !== 'authorization' && // Skip Supabase auth
|
|
|
|
|
+ !lowerKey.startsWith('x-shoprenter-') &&
|
|
|
|
|
+ !lowerKey.startsWith('x-client-info')
|
|
|
|
|
+ ) {
|
|
|
shopRenterHeaders.set(key, value)
|
|
shopRenterHeaders.set(key, value)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Set Authorization header with ShopRenter token
|
|
|
|
|
+ shopRenterHeaders.set('Authorization', `Bearer ${shopRenterToken}`)
|
|
|
|
|
+
|
|
|
// Ensure required headers are present
|
|
// Ensure required headers are present
|
|
|
if (!shopRenterHeaders.has('Content-Type')) {
|
|
if (!shopRenterHeaders.has('Content-Type')) {
|
|
|
shopRenterHeaders.set('Content-Type', 'application/json')
|
|
shopRenterHeaders.set('Content-Type', 'application/json')
|
|
@@ -120,8 +130,6 @@ serve(async (req) => {
|
|
|
method: req.method,
|
|
method: req.method,
|
|
|
headers: shopRenterHeaders,
|
|
headers: shopRenterHeaders,
|
|
|
body: body,
|
|
body: body,
|
|
|
- // Force HTTP/1.1 to avoid ShopRenter API issues
|
|
|
|
|
- // Note: This is handled by Deno's fetch by default
|
|
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
console.log(`[ShopRenter Proxy] ShopRenter API responded with status: ${shopRenterResponse.status}`)
|
|
console.log(`[ShopRenter Proxy] ShopRenter API responded with status: ${shopRenterResponse.status}`)
|