Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/graphql / src / proxy.ts
Size: Mime:
/**
 * @file @todo split up
 */
/* eslint-disable import/first */
/* eslint-disable import/no-namespace */
// import { Cookie, CookieJar } from 'tough-cookie'
import proxy from 'http-proxy-middleware'
import express from 'express'
import { NextFunction, Request, Response } from 'express';
import cookieParser from 'cookie-parser'
import bodyParser from 'body-parser'
import { isArray, isObj, isTrue, isEmpty } from 'uxui-modules/exotic'
import { cookies } from 'uxui-modules/persistance/cookies'
import oneStorage from 'uxui-modules/persistance/local-storage'
import modifyResponse from 'uxui-modules/_forks/node-http-proxy-json'
import isErrorLikeResponse from 'uxui-modules/oneRequest/deps/isErrorLikeResponse'
import fromRequestToHash from 'uxui-modules/oneRequest/deps/fromRequestToHash'
import * as config from './bootstrapper/api/config'
import {
  // apiConfig,
  // https,
  // baseUrlPrefix,
  // getBaseTargetURL,
  getURL,
  endpoints,
  callDetails,
} from './deps/transformRequestProxy'
import { createCookieHacker, fromObjCookiesToString } from './deps/cookieHacker'
import { encodeBody } from './deps/encodeBody'
import { cacheResponse, clearCache, nocache } from './deps/networkCache'
import { logReqAndOrRes } from './deps/fromReqResToDebug'
const { cookieConfig } = config

// ----- we use this so we can just call /api/category not /category
// ----- always enabled, this way we can know it goes to api
// ----- and is not requesting a page or other data
const pathRewrite = {
  '^/api': '/',
}

const getProxyUrl = (route, callType) => {
  const proxyConfig = {
    changeOrigin: true,
    secure: true,
    pathRewrite,
    onProxyRes,
    onProxyReq,
    dataType: 'json',
    logLevel: 'silent',
    // target: route,
    target: getURL(route, callType),
  }
  // proxyConfig.target = getURL(route, callType)
  return proxyConfig
}

// https://www.npmjs.com/package/http-proxy#options
// ^ cookie rewrite
// eslint-disable-next-line
function onProxyRes(proxyRes, req: Request, res: Response, next: NextFunction) {
  console.log('[uxui-api] onProxyRes')

  const { authCookies, onCookie } = createCookieHacker()
  // isEmpty(authCookies) &&
  if (isArray(proxyRes.headers['set-cookie'])) {
    // oneStorage.removeItem('authCookies')
    proxyRes.headers['set-cookie'].map(onCookie)

    modifyResponse(res, proxyRes, body => {
      // const safe = 'authCookies' + authCookies.join('_')
      // oneStorage.setItem(safe, authCookies)
      body.cookies = authCookies

      if (process.env.SERVER_NETWORK_CACHE === true) {
        cacheResponse(res, body)
      }
      return body
    })
  } else {
    modifyResponse(res, proxyRes, body => {
      if (process.env.SERVER_NETWORK_CACHE === true) {
        cacheResponse(res, body)
      }
      return body
    })
  }
  delete proxyRes.headers['set-cookie']
  proxyRes.headers['set-cookie'] = authCookies
}

interface ProxyRequest extends Request {
  setHeader(key: string, value: any): void
  write(body: string): any
  end(): any
}

// eslint-disable-next-line
function onProxyReq(proxyReq: ProxyRequest, req: Request, res: Response, next: NextFunction) {
  console.log('[uxui-api] onProxyReq')
  const requestCookies = req.cookies
  console.log('onProxyReq______', {
    requestCookies,
    cookieMagic: global.cookieMagic,
  })

  // require('fliplog').quick({
  //   // proxyReq,
  //   req,
  // })
  // console.log({ proxyheaders: proxyReq.headers })
  // console.log({ headers: req.headers })
  // const safeRequestCookies = req.cookies || req.headers._cookie || req.signedCookies
  // const requestCookies = isObj(safeRequestCookies) && Object.keys(safeRequestCookies).length > 0
  //   ? safeRequestCookies
  //   : global.cookieMagic
  // console.log('onProxyReq______', {
  //   requestCookies,
  //   cook: req.cookies,
  //   cookiez: req.headers.cookie,
  //   _cookie: req.headers._cookie,
  //   signedCookies: req.signedCookies,
  //   cookieMagic: global.cookieMagic,
  // })

  if (process.env.TEST_COOKIE_SCOPE) {
    // testing - can do .forEach & console.assert too
    Object.keys(requestCookies).forEach(key => {
      if (global.cookieMagic[key] !== requestCookies[key]) {
        throw new Error('PROVEN FIX')
      } else {
        console.log('was the same value for ' + key)
      }
    })
  }

  // const HORRIBLE_GLOBALS_THANKS_TO_APOLLO = fromObjCookiesToString(global.cookieMagic)
  const HORRIBLE_GLOBALS_THANKS_TO_APOLLO = fromObjCookiesToString(requestCookies)

  proxyReq.setHeader('Cookie', HORRIBLE_GLOBALS_THANKS_TO_APOLLO)
  //   console.log('HORRIBLE_GLOBALS_THANKS_TO_APOLLO', HORRIBLE_GLOBALS_THANKS_TO_APOLLO)

  if (req.method === 'POST' && !isEmpty(req.body)) {
    console.log('[uxui-apis] encoding body')
    const reqBody = req.body
    delete req.body
    // console.log('Old Body', reqBody)
    const body = encodeBody(reqBody)
    if (process.env.LOG_REQUEST_POST_BODY) {
      console.log('[uxui-apis] ', { reqBody, body })
    }

    proxyReq.setHeader('content-type', 'application/x-www-form-urlencoded')
    proxyReq.setHeader('content-length', body.length)
    proxyReq.write(body)
    proxyReq.end()
  } else {
    console.log('[uxui-apis] not encoding body')
    if (process.env.LOG_REQUEST_PROXY) {
      console.log('[uxui-apis] LOG_REQUEST_PROXY', req)
    }
  }
}

const proxyApi = api => {
  const fromRouteToProxy = route => {
    const proxyConfig = getProxyUrl(route, callDetails[route])
    const proxyMiddlewareForRoute = proxy(proxyConfig)

    // @note removed for now
    // createProxyCache

    api.use(route, proxyMiddlewareForRoute)
    return api
  }

  endpoints.map(fromRouteToProxy)
  return api

  // @NOTE when we need more advanced config, we do not put it in endpoints
  // api.use('/user', proxy(proxyConfig))

  // 20170815175328
  // http://localhost:3000/api/category/top?campaignId=2495&subcategory=true
  // http://localhost:4000/api/search?campaignId=2495&offset=0&limit=15&locale=en_US&search=shoe
}

// @NOTE may want to not use this in test env
const api = express()

api.use(function(req, res, next) {
  res.req = req

  const reqRes = {
    req,
    res,
  }

  logReqAndOrRes(reqRes)
  next()
})
api.use(cookieParser())
api.use(bodyParser.json())
api.use(
  bodyParser.urlencoded({
    extended: true,
  })
)
proxyApi(api)

export { api }
export default api