import * as http from 'http' ; import * as https from 'https' ; import * as url from 'url' ; import * as fs from 'fs' ; import { makePlantumlURL } from '../plantumlURL' ; import { Diagram , diagramStartReg } from '../diagram/diagram' ; import { RenderError } from './interfaces' ; import { HTTPErrorType , HTTPError } from './httpErrors' ; export function httpWrapper ( method , server , diagram , format , index , savePath ? ) { let requestPath , requestUrl ; requestPath = [ server , format , index , "..." ] . join ( "/" ) ; switch ( method ) { case "GET" : requestUrl = makePlantumlURL ( server , diagram , format , index ) ; break ; case "POST" : requestUrl = [ server , format , index , "om80" ] . join ( "/" ) ; break ; default : return Promise . reject ( "Unsupported request method: " + method ) ; } return new Promise < Buffer > ( ( resolve , reject ) => { let buffBody = [ ] ; let buffBodyLen = 0 ; let response ; let httpError ; let u = url . parse ( requestUrl ) ; let options = < https . RequestOptions > { protocol : u . protocol , auth : u . auth , host : u . host , hostname : u . hostname , port : parseInt ( u . port ) , path : u . path , method : method , headers : { "Content-Type" : 'text/plain; charset=utf-8' , } , } ; let responseCallback = ( res ) => { response = res ; res . on ( 'data' , function ( chunk ) { buffBody . push ( chunk ) ; buffBodyLen += chunk . length ; } ) ; } ; let closeCallback = ( ) => { if ( httpError ) { reject ( httpError ) ; return ; } let body = Buffer . concat ( buffBody , buffBodyLen ) ; if ( response . statusCode === 200 ) { if ( savePath ) { if ( body . length ) { fs . writeFileSync ( savePath , body ) ; body = Buffer . from ( savePath ) ; } else { body = Buffer . from ( "" ) ; } } resolve ( body ) ; } else if ( response . headers [ 'x-plantuml-diagram-error' ] ) { let msg = parsePlantumlError ( response . headers [ 'x-plantuml-diagram-error' ] , parseInt ( response . headers [ 'x-plantuml-diagram-error-line' ] ) , response . headers [ 'x-plantuml-diagram-description' ] , diagram ) ; reject ( < RenderError > { error : msg , out : body } ) ; } else { let err = new Error ( response . statusCode + " " + response . statusMessage + "\n\n" + method + " " + requestPath ) ; httpError = new HTTPError ( err , HTTPErrorType . ResponeError , response . statusCode ) ; reject ( httpError ) ; } } ; let req = u . protocol == "http:" ? http . request ( options , responseCallback ) : https . request ( options , responseCallback ) ; req . on ( 'error' , ( err ) => { httpError = new HTTPError ( err , HTTPErrorType . NetworkError ) ; } ) ; req . on ( 'close' , closeCallback ) ; if ( method == "POST" ) { req . write ( diagram . contentWithInclude , "utf8" ) ; } req . end ( ) ; } ) ; } function parsePlantumlError ( error , line , description , diagram ) { if ( diagramStartReg . test ( diagram . lines [ 0 ] ) ) line += 1 ; let fileLine = line ; let blankLineCount = 0 ; for ( let i = 1 ; i < diagram . lines . length ; i ++ ) { if ( diagram . lines [ i ] . trim ( ) ) break ; blankLineCount ++ ; } fileLine += blankLineCount ; let lineContent = diagram . lines [ fileLine - 1 ] ; fileLine += diagram . start . line ; return `${ error } (@ Diagram Line ${ line }, File Line ${ fileLine })\n"${ lineContent }"\n${ description }\n` ; }