This repository has been archived by the owner on Sep 5, 2023. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
123 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* @module Backends | ||
*/ | ||
|
||
import { proxy, ProxyFunction } from "../proxy"; | ||
import { normalizeOptions, SubdomainOptions } from "./subdomain_service"; | ||
|
||
/** | ||
* Creates a `fetch` like function for proxying requests to hosted Netlify sites. | ||
* @param options Netlify site information. Accepts subdomain as a string. | ||
*/ | ||
export function netlify(options: SubdomainOptions | string): ProxyFunction<SubdomainOptions> { | ||
const config = normalizeOptions(options); | ||
|
||
const netlifyHost = `${config.subdomain}.netlify.com` | ||
const uri = `https://${netlifyHost}${config.directory}` | ||
const headers = { | ||
"host": netlifyHost, | ||
"x-forwarded-host": config.hostname || false | ||
} | ||
|
||
const fn = proxy(uri, { headers: headers }) | ||
return Object.assign(fn, { proxyConfig: config}) | ||
} | ||
|
||
netlify.normalizeOptions = normalizeOptions; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { isObject, merge } from "../util"; | ||
import * as errors from "../errors"; | ||
export interface SubdomainOptions { | ||
/** Blog's subdomain: <subdomain>.netlify.com */ | ||
subdomain: string, | ||
/** Subdirectory site is served from (if any) */ | ||
directory?: string, | ||
/** Netlify sites can be configured with a custom hostname, we need that to proxy properly */ | ||
hostname?: string | ||
} | ||
|
||
export function normalizeOptions(input: unknown): SubdomainOptions { | ||
const options: SubdomainOptions = { | ||
subdomain: "", | ||
directory: "/" | ||
}; | ||
|
||
if (typeof input === "string") { | ||
options.subdomain = input; | ||
} else if (isObject(input)) { | ||
merge(options, input, ["subdomain", "directory", "hostname"]); | ||
} else { | ||
throw errors.invalidInput("options must be a NetlifyProOptions object or string"); | ||
} | ||
|
||
if (!options.subdomain) { | ||
throw errors.invalidProperty("subdomain", "is required"); | ||
} | ||
|
||
return options; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,72 @@ | ||
import { expect } from "chai"; | ||
import { ghostProBlog, glitch } from "../../src/backends" | ||
import { ghostProBlog, glitch, netlify } from "../../src/backends" | ||
import * as errors from "../../src/errors"; | ||
import { normalizeOptions } from "../../src/backends/subdomain_service"; | ||
|
||
const defs = [ | ||
{ backend: ghostProBlog, subdomain: "fly-io" }, | ||
{ backend: glitch, subdomain: "fly-example", options: ["subdomain"] } | ||
{ backend: ghostProBlog, tests: [ | ||
{ subdomain: "fly-io", hostname: 'fly.io', directory: "/articles/" }, | ||
{ subdomain: "demo" } | ||
]}, | ||
{ backend: glitch, options: ["subdomain"], tests: [ | ||
{subdomain: "fly-example" }, | ||
]}, | ||
{ backend: netlify, options: ["subdomain", "directory"], tests: [{ | ||
subdomain: "example"} | ||
]} | ||
] | ||
for(const d of defs){ | ||
const backend = d.backend | ||
describe(`backends/${backend.name}`, function() { | ||
this.timeout(15000) | ||
|
||
describe("options", () => { | ||
const validOptions = [ | ||
[ | ||
"subdomain", | ||
{ subdomain: "subdomain", directory: "/" } | ||
], | ||
[ | ||
{ subdomain: "subdomain" }, | ||
{ subdomain: "subdomain", directory: "/" } | ||
], | ||
[ | ||
{ subdomain: "subdomain", hostname: "host.name" }, | ||
{ subdomain: "subdomain", directory: "/", hostname: "host.name" } | ||
], | ||
[ | ||
{ subdomain: "subdomain", directory: "/" }, | ||
{ subdomain: "subdomain", directory: "/" } | ||
] | ||
]; | ||
|
||
for (const [input, c] of validOptions) { | ||
const config:any = Object.assign({}, c) | ||
console.log("checking:", input, config) | ||
it(`accepts ${JSON.stringify(input)}`, () => { | ||
if(d.options){ | ||
for(const k of Object.getOwnPropertyNames(config)){ | ||
if(!d.options.includes(k)){ | ||
console.log("deleting key:", k) | ||
delete config[k] | ||
} | ||
} | ||
} | ||
expect(backend(input as any).proxyConfig).to.eql(config); | ||
}) | ||
} | ||
|
||
const invalidOptions = [ | ||
[undefined, errors.InputError], | ||
["", /subdomain is required/], | ||
[{}, /subdomain is required/], | ||
[{ subdomain: "" }, /subdomain is required/], | ||
]; | ||
|
||
for (const [input, err] of invalidOptions) { | ||
it(`rejects ${JSON.stringify(input)}`, () => { | ||
expect(() => { ghostProBlog(input as any) }).throw(err as any); | ||
}) | ||
} | ||
}) | ||
for(const t of d.tests){ | ||
it(`works with settings: ${JSON.stringify(t)}`, async () => { | ||
const fn = backend(t as any); | ||
|
||
const resp = await fn("https://backend/", { method: "HEAD"}) | ||
expect(resp.status).to.eq(200) | ||
}) | ||
} | ||
}) | ||
} | ||
|
||
it('works with just a subdomain', async () => { | ||
const fn = backend({ subdomain: "demo" }); | ||
describe("backends/subdomainService", () => { | ||
const validOptions = [ | ||
[ | ||
"subdomain", | ||
{ subdomain: "subdomain", directory: "/" } | ||
], | ||
[ | ||
{ subdomain: "subdomain" }, | ||
{ subdomain: "subdomain", directory: "/" } | ||
], | ||
[ | ||
{ subdomain: "subdomain", hostname: "host.name" }, | ||
{ subdomain: "subdomain", directory: "/", hostname: "host.name" } | ||
], | ||
[ | ||
{ subdomain: "subdomain", directory: "/" }, | ||
{ subdomain: "subdomain", directory: "/" } | ||
] | ||
]; | ||
|
||
const resp = await fn("https://backend/", { method: "HEAD"}) | ||
expect(resp.status).to.eq(200) | ||
for (const [input, config] of validOptions) { | ||
it(`normalizes ${JSON.stringify(input)}`, () => { | ||
expect(normalizeOptions(input)).to.eql(config); | ||
}) | ||
} | ||
|
||
it('works with a custom domain and directory', async () =>{ | ||
const fn = backend(<any>{ | ||
subdomain: d.subdomain, | ||
hostname: "fly.io", | ||
directory: "/articles/" | ||
}) | ||
const invalidOptions = [ | ||
[undefined, errors.InputError], | ||
["", /subdomain is required/], | ||
[{}, /subdomain is required/], | ||
[{ subdomain: "" }, /subdomain is required/], | ||
]; | ||
|
||
const resp = await fn("https://backend/", { method: "HEAD"}) | ||
expect(resp.status).to.eq(200) | ||
for (const [input, err] of invalidOptions) { | ||
it(`rejects ${JSON.stringify(input)}`, () => { | ||
expect(() => { normalizeOptions(input) }).throw(err as any); | ||
}) | ||
}) | ||
} | ||
} | ||
}) |