1
+ // @flow
2
+
1
3
const https = require ( 'https' ) ;
2
4
const PixelStream = require ( 'pixel-stream' ) ;
3
5
const neuquant = require ( 'neuquant' ) ;
@@ -6,16 +8,19 @@ const GifEncoder = require('gif-stream/encoder');
6
8
const inherits = require ( 'util' ) . inherits ;
7
9
8
10
function ConcatFrames ( callback ) {
9
- if ( ! ( this instanceof ConcatFrames ) ) return new ConcatFrames ( callback ) ;
10
-
11
- PixelStream . call ( this ) ;
12
-
13
- this . frame = null ;
14
- this . buffers = [ ] ;
15
- this . callback = callback ;
16
-
17
- // put the stream in flowing mode
18
- this . resume ( ) ;
11
+ const concatFrames = this ;
12
+ if ( concatFrames instanceof ConcatFrames ) {
13
+ PixelStream . call ( concatFrames ) ;
14
+
15
+ concatFrames . frame = null ;
16
+ concatFrames . buffers = [ ] ;
17
+ concatFrames . callback = callback ;
18
+
19
+ // put the stream in flowing mode
20
+ concatFrames . resume ( ) ;
21
+ } else {
22
+ return new ConcatFrames ( callback ) ;
23
+ }
19
24
}
20
25
21
26
inherits ( ConcatFrames , PixelStream ) ;
@@ -50,8 +55,8 @@ ConcatFrames.prototype._end = function (done) {
50
55
51
56
const MAX_REDIRECT_DEPTH = 5 ;
52
57
53
- export function getWithRedirect ( url , cb , depth = 1 ) {
54
- return https . get ( url , ( resp ) => {
58
+ export function getWithRedirect ( url : URL , cb : any , depth : number = 1 ) {
59
+ return https . get ( url . toString ( ) , ( resp ) => {
55
60
if (
56
61
resp . statusCode > 300 &&
57
62
resp . statusCode < 400 &&
@@ -79,15 +84,20 @@ function padBase64String(input: string): string {
79
84
return `${ input } ${ pad } ` ;
80
85
}
81
86
82
- function decodeUrl ( base64Url ) {
83
- return Buffer . from (
84
- padBase64String ( base64Url ) . replace ( / - / g, '+' ) . replace ( / _ / g, '/' ) ,
85
- 'base64' ,
86
- ) . toString ( 'utf-8' ) ;
87
+ function decodeUrl ( base64Url : string ) : URL | Error {
88
+ try {
89
+ const url = Buffer . from (
90
+ padBase64String ( base64Url ) . replace ( / - / g, '+' ) . replace ( / _ / g, '/' ) ,
91
+ 'base64' ,
92
+ ) . toString ( 'utf-8' ) ;
93
+ return new URL ( url ) ;
94
+ } catch ( e ) {
95
+ return e ;
96
+ }
87
97
}
88
98
89
- function isGitHubUrl ( url : string ) : boolean {
90
- const host = new URL ( url ) . host ;
99
+ function isGitHubUrl ( url : URL ) : boolean {
100
+ const host = url . host ;
91
101
const parts = host . split ( '.' ) ;
92
102
return (
93
103
parts . length >= 2 &&
@@ -97,7 +107,7 @@ function isGitHubUrl(url: string): boolean {
97
107
}
98
108
99
109
// workaround for netlify (res.redirect is broken)
100
- function redirect ( res , statusOrUrl , url ) {
110
+ function redirect ( res , statusOrUrl : string | number , url ?: ? string ) {
101
111
if ( typeof statusOrUrl === 'string' ) {
102
112
url = statusOrUrl ;
103
113
statusOrUrl = 307 ;
@@ -112,12 +122,18 @@ function redirect(res, statusOrUrl, url) {
112
122
return res ;
113
123
}
114
124
115
- export const firstFrame = ( req , res ) => {
125
+ export const firstFrame = ( req : any , res : any ) => {
116
126
const url = decodeUrl ( req . params . base64Url ) ;
117
127
128
+ if ( url instanceof Error ) {
129
+ res . status ( 400 ) ;
130
+ res . send ( 'Invalid URL.' ) ;
131
+ return ;
132
+ }
133
+
118
134
if ( ! isGitHubUrl ( url ) ) {
119
- console . warn ( 'Non-GitHub url, redirecting' , url ) ;
120
- redirect ( res , url ) ;
135
+ console . warn ( 'Non-GitHub url, redirecting' , url . toString ( ) ) ;
136
+ redirect ( res , url . toString ( ) ) ;
121
137
return ;
122
138
}
123
139
@@ -141,10 +157,10 @@ export const firstFrame = (req, res) => {
141
157
} ) ;
142
158
} ;
143
159
144
- export const proxyImage = ( res , url ) => {
160
+ export const proxyImage = ( res : any , url : URL ) : any => {
145
161
if ( ! isGitHubUrl ( url ) ) {
146
- console . warn ( 'Non-GitHub url, redirecting' , url ) ;
147
- redirect ( res , url ) ;
162
+ console . warn ( 'Non-GitHub url, redirecting' , url . toString ( ) ) ;
163
+ redirect ( res , url . toString ( ) ) ;
148
164
return ;
149
165
}
150
166
@@ -158,7 +174,7 @@ export const proxyImage = (res, url) => {
158
174
}
159
175
if ( contentLength && contentLength >= 4500000 ) {
160
176
// Lambda can't handle anything larger than 5mb, so we'll redirect to the original url instead
161
- redirect ( res , url ) ;
177
+ redirect ( res , url . toString ( ) ) ;
162
178
} else {
163
179
res . status ( resp . statusCode ) ;
164
180
for ( const k of Object . keys ( resp . headers ) ) {
@@ -185,8 +201,13 @@ export const proxyImage = (res, url) => {
185
201
} ) ;
186
202
} ;
187
203
188
- export const imageProxy = async ( req , res ) => {
204
+ export const imageProxy = async ( req : any , res : any ) => {
189
205
const url = decodeUrl ( req . params . base64Url ) ;
206
+ if ( url instanceof Error ) {
207
+ res . status ( 400 ) ;
208
+ res . send ( 'Invalid URL.' ) ;
209
+ return ;
210
+ }
190
211
await proxyImage ( res , url ) ;
191
212
return ;
192
213
} ;
0 commit comments