1
1
'use strict' ;
2
2
3
+ const trimNewlines = require ( 'trim-newlines' ) ;
3
4
const debugLog = require ( './debugLog' ) ;
4
5
const fork = require ( 'child_process' ) . fork ;
5
6
const _ = require ( 'lodash' ) ;
@@ -9,52 +10,76 @@ const uuid = require('uuid/v4');
9
10
const handlerCache = { } ;
10
11
const messageCallbacks = { } ;
11
12
12
- function runPythonHandler ( funOptions , options ) {
13
+ function runPythonHandler ( funOptions , options ) {
13
14
var spawn = require ( "child_process" ) . spawn ;
14
- return function ( event , context ) {
15
- var process = spawn ( 'sls' , [ "invoke" , "local" , "-f" , funOptions . funName ] ,
16
- { stdio : [ 'pipe' , 'pipe' , 'pipe' ] , shell : true , cwd :funOptions . servicePath } ) ;
17
- process . stdin . write ( JSON . stringify ( event ) + "\n" ) ;
18
- process . stdin . end ( ) ;
19
- let results = ''
20
- process . stdout . on ( 'data' , ( data ) => {
21
- results = results + data ;
22
- } ) ;
23
- process . stderr . on ( 'data' , ( data ) => {
24
- context . fail ( data ) ;
25
- } ) ;
26
- process . on ( 'close' , ( code ) => {
27
- if ( code == 0 ) {
28
- try {
29
- context . succeed ( JSON . parse ( results ) ) ;
30
- } catch ( ex ) {
31
- context . fail ( results ) ;
32
- }
33
- } else {
34
- context . succeed ( code , results ) ;
35
- }
15
+ return function ( event , context ) {
16
+ var process = spawn ( 'sls' , [ "invoke" , "local" , "-f" , funOptions . funName ] ,
17
+ { stdio : [ 'pipe' , 'pipe' , 'pipe' ] , shell : true , cwd : funOptions . servicePath } ) ;
18
+ process . stdin . write ( JSON . stringify ( event ) + "\n" ) ;
19
+ process . stdin . end ( ) ;
20
+ let results = ''
21
+ let hasDetectedJson = false ;
22
+ process . stdout . on ( 'data' , ( data ) => {
23
+ let str = data . toString ( 'utf8' ) ;
24
+ if ( hasDetectedJson ) {
25
+ // Assumes that all data after matching the start of the
26
+ // JSON result is the rest of the context result.
27
+ results = results + trimNewlines ( str ) ;
28
+ } else {
29
+ // Search for the start of the JSON result
30
+ // https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
31
+ const match = / { \n \s + " i s B a s e 6 4 E n c o d e d " | { \n \s + " s t a t u s C o d e " | { \n \s + " h e a d e r s " | { \n \s + " b o d y " / . exec ( str ) ;
32
+ if ( match && match . index > - 1 ) {
33
+ // The JSON result was in this chunk so slice it out
34
+ hasDetectedJson = true ;
35
+ results = results + trimNewlines ( str . slice ( match . index ) ) ;
36
+ str = str . slice ( 0 , match . index ) ;
37
+ }
38
+
39
+ if ( str . length > 0 ) {
40
+ // The data does not look like JSON and we have not
41
+ // detected the start of JSON, so write the
42
+ // output to the console instead.
43
+ console . log ( 'Python:' , '\x1b[34m' + str + '\x1b[0m' ) ;
44
+ }
45
+ }
36
46
} ) ;
37
- }
47
+ process . stderr . on ( 'data' , ( data ) => {
48
+ context . fail ( data ) ;
49
+ } ) ;
50
+ process . on ( 'close' , ( code ) => {
51
+ if ( code == 0 ) {
52
+ try {
53
+ context . succeed ( JSON . parse ( results ) ) ;
54
+ } catch ( ex ) {
55
+ context . fail ( results ) ;
56
+ }
57
+ } else {
58
+ context . succeed ( code , results ) ;
59
+ }
60
+ } ) ;
61
+ }
38
62
}
39
63
64
+
40
65
module . exports = {
41
- getFunctionOptions ( fun , funName , servicePath , serviceRuntime ) {
42
- console . log ( fun , funName , servicePath )
43
- // Split handler into method name and path i.e. handler.run
44
- const handlerFile = fun . handler . split ( '.' ) [ 0 ] ;
45
- const handlerName = fun . handler . split ( '/' ) . pop ( ) . split ( '.' ) [ 1 ] ;
46
-
47
- return {
48
- funName,
49
- handlerName, // i.e. run
50
- handlerFile,
51
- handlerPath : `${ servicePath } /${ handlerFile } ` ,
52
- servicePath,
53
- funTimeout : ( fun . timeout || 30 ) * 1000 ,
54
- babelOptions : ( ( fun . custom || { } ) . runtime || { } ) . babel ,
55
- serviceRuntime,
56
- } ;
57
- } ,
66
+ getFunctionOptions ( fun , funName , servicePath , serviceRuntime ) {
67
+ console . log ( fun , funName , servicePath )
68
+ // Split handler into method name and path i.e. handler.run
69
+ const handlerFile = fun . handler . split ( '.' ) [ 0 ] ;
70
+ const handlerName = fun . handler . split ( '/' ) . pop ( ) . split ( '.' ) [ 1 ] ;
71
+
72
+ return {
73
+ funName,
74
+ handlerName, // i.e. run
75
+ handlerFile,
76
+ handlerPath : `${ servicePath } /${ handlerFile } ` ,
77
+ servicePath,
78
+ funTimeout : ( fun . timeout || 30 ) * 1000 ,
79
+ babelOptions : ( ( fun . custom || { } ) . runtime || { } ) . babel ,
80
+ serviceRuntime,
81
+ } ;
82
+ } ,
58
83
59
84
createExternalHandler ( funOptions , options ) {
60
85
let handlerContext = handlerCache [ funOptions . handlerPath ] ;
0 commit comments