text:
import compression from 'next/dist/compiled/compression'
import fs from 'fs'
import chalk from 'chalk'
import { IncomingMessage, ServerResponse } from 'http'
import Proxy from 'next/dist/compiled/http-proxy'
import { join, relative, resolve, sep } from 'path'
import {
  parse as parseQs,
  stringify as stringifyQs,
  ParsedUrlQuery,
} from 'querystring'
import { format as formatUrl, parse as parseUrl, UrlWithParsedQuery } from 'url'
import { PrerenderManifest } from '../build'
import {
  getRedirectStatus,
  Header,
  Redirect,
  Rewrite,
  RouteType,
  CustomRoutes,
  modifyRouteRegex,
} from '../lib/load-custom-routes'
import {
  BUILD_ID_FILE,
  CLIENT_PUBLIC_FILES_PATH,
  CLIENT_STATIC_FILES_PATH,
  CLIENT_STATIC_FILES_RUNTIME,
  PAGES_MANIFEST,
  PERMANENT_REDIRECT_STATUS,
  PRERENDER_MANIFEST,
  ROUTES_MANIFEST,
  SERVERLESS_DIRECTORY,
  SERVER_DIRECTORY,
  STATIC_STATUS_PAGES,
  TEMPORARY_REDIRECT_STATUS,
} from '../shared/lib/constants'
import {
  getRouteMatcher,
  getRouteRegex,
  getSortedRoutes,
  isDynamicRoute,
} from '../shared/lib/router/utils'
import * as envConfig from '../shared/lib/runtime-config'
import {
  DecodeError,
  isResSent,
  NextApiRequest,
  NextApiResponse,
  normalizeRepeatedSlashes,
} from '../shared/lib/utils'
import {
  apiResolver,
  setLazyProp,
  getCookieParser,
  tryGetPreviewData,
  __ApiPreviewProps,
} from './api-utils'
import { DomainLocale, isTargetLikeServerless, NextConfig } from './config'
import pathMatch from '../shared/lib/router/utils/path-match'
import { recursiveReadDirSync } from './lib/recursive-readdir-sync'
import { loadComponents, LoadComponentsReturnType } from './load-components'
import { normalizePagePath } from './normalize-page-path'
import { RenderOpts, RenderOptsPartial, renderToHTML } from './render'
import { getPagePath, requireFontManifest } from './require'
import Router, {
  DynamicRoutes,
  PageChecker,
  Params,
  route,
  Route,
} from './router'
import prepareDestination, {
  compileNonPath,
} from '../shared/lib/router/utils/prepare-destination'
import { sendRenderResult, setRevalidateHeaders } from './send-payload'
import { serveStatic } from './serve-static'
import { IncrementalCache } from './incremental-cache'
import { execOnce } from '../shared/lib/utils'
import { isBlockedPage, isBot } from './utils'
import RenderResult from './render-result'
import { loadEnvConfig } from '@next/env'
import './node-polyfill-fetch'
import { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin'
import { removePathTrailingSlash } from '../client/normalize-trailing-slash'
import getRouteFromAssetPath from '../shared/lib/router/utils/get-route-from-asset-path'
import { FontManifest } from './font-utils'
import { denormalizePagePath } from './denormalize-page-path'
import { normalizeLocalePath } from '../shared/lib/i18n/normalize-locale-path'
import * as Log from '../build/output/log'
import { detectDomainLocale } from '../shared/lib/i18n/detect-domain-locale'
import escapePathDelimiters from '../shared/lib/router/utils/escape-path-delimiters'
import { getUtils } from '../build/webpack/loaders/next-serverless-loader/utils'
import { PreviewData } from 'next/types'
import ResponseCache, {
  ResponseCacheEntry,
  ResponseCacheValue,
} from './response-cache'
import { NextConfigComplete } from './config-shared'
import { parseNextUrl } from '../shared/lib/router/utils/parse-next-url'
import isError from '../lib/is-error'

const getCustomRouteMatcher = pathMatch(true)

type Middleware = (
  req: IncomingMessage,
  res: ServerResponse,
  next: (err?: Error) => void
) => void

export type FindComponentsResult = {
  components: LoadComponentsReturnType
  query: ParsedUrlQuery
}

type DynamicRouteItem = {
  page: string
  match: ReturnType<typeof getRouteMatcher>
}

export type ServerConstructor = {
  /**
   * Where the Next project is located - @default '.'
   */
  dir?: string
  /**
   * Hide error messages containing server information - @default false
   */
  quiet?: boolean
  /**
   * Object what you would use in next.config.js - @default {}
   */
  conf?: NextConfig | null
  dev?: boolean
  customServer?: boolean
}

type RequestContext = {
  req: IncomingMessage
  res: ServerResponse
  pathname: string
  query: ParsedUrlQuery
  renderOpts: RenderOptsPartial
}

export default class Server {
  protected dir: string
  protected quiet: boolean
  protected nextConfig: NextConfigComplete
  protected distDir: string
  protected pagesDir?: string
  protected publicDir: string
  protected hasStaticDir: boolean
  protected serverBuildDir: string
  protected pagesManifest?: PagesManifest
  protected buildId: string
  protected minimalMode: boolean
  protected renderOpts: {
    poweredByHeader: boolean
    buildId: string
    generateEtags: boolean
    runtimeConfig?: { [key: string]: any }
    assetPrefix?: string
    canonicalBase: string
    dev?: boolean
    previewProps: __ApiPreviewProps
    customServer?: boolean
    ampOptimizerConfig?: { [key: string]: any }
    basePath: string
    optimizeFonts: boolean
    images: string
    fontManifest: FontManifest
    optimizeImages: boolean
    disableOptimizedLoading?: boolean
    optimizeCss: any
    locale?: string
    locales?: string[]
    defaultLocale?: string
    domainLocales?: DomainLocale[]
    distDir: string
    concurrentFeatures?: boolean
  }
  private compression?: Middleware
  private incrementalCache: IncrementalCache
  private responseCache: ResponseCache
  protected router: Router
  protected dynamicRoutes?: DynamicRoutes
  protected customRoutes: CustomRoutes

  public constructor({
    dir = '.',
    quiet = false,
    conf,
    dev = false,
    minimalMode = false,
    customServer = true,
  }: ServerConstructor & { conf: NextConfig; minimalMode?: boolean }) {
    this.dir = resolve(dir)
    this.quiet = quiet
    loadEnvConfig(this.dir, dev, Log)

    this.nextConfig = conf as NextConfigComplete

    this.distDir = join(this.dir, this.nextConfig.distDir)
    this.publicDir = join(this.dir, CLIENT_PUBLIC_FILES_PATH)
    this.hasStaticDir = !minimalMode && fs.existsSync(join(this.dir, 'static'))

    // Only serverRuntimeConfig needs the default
    // publicRuntimeConfig gets it's default in client/index.js
    const {
      serverRuntimeConfig = {},
      publicRuntimeConfig,
      assetPrefix,
      generateEtags,
      compress,
    } = this.nextConfig

    this.buildId = this.readBuildId()
    this.minimalMode = minimalMode

    this.renderOpts = {
      poweredByHeader: this.nextConfig.poweredByHeader,
      canonicalBase: this.nextConfig.amp.canonicalBase || '',
      buildId: this.buildId,
      generateEtags,
      previewProps: this.getPreviewProps(),
      customServer: customServer === true ? true : undefined,
      ampOptimizerConfig: this.nextConfig.experimental.amp?.optimizer,
      basePath: this.nextConfig.basePath,
      images: JSON.stringify(this.nextConfig.images),
      optimizeFonts: !!this.nextConfig.optimizeFonts && !dev,
      fontManifest:
        this.nextConfig.optimizeFonts && !dev
          ? requireFontManifest(this.distDir, this._isLikeServerless)
          : null,
      optimizeImages: !!this.nextConfig.experimental.optimizeImages,
      optimizeCss: this.nextConfig.experimental.optimizeCss,
      disableOptimizedLoading:
        this.nextConfig.experimental.disableOptimizedLoading,
      domainLocales: this.nextConfig.i18n?.domains,
      distDir: this.distDir,
      concurrentFeatures: this.nextConfig.experimental.concurrentFeatures,
    }

    // Only the `publicRuntimeConfig` key is exposed to the client side
    // It'll be rendered as part of __NEXT_DATA__ on the client side
    if (Object.keys(publicRuntimeConfig).length > 0) {
      this.renderOpts.runtimeConfig = publicRuntimeConfig
    }

    if (compress && this.nextConfig.target === 'server') {
      this.compression = compression() as Middleware
    }

    // Initialize next/config with the environment configuration
    envConfig.setConfig({
      serverRuntimeConfig,
      publicRuntimeConfig,
    })

    this.serverBuildDir = join(
      this.distDir,
      this._isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY
    )
    const pagesManifestPath = join(this.serverBuildDir, PAGES_MANIFEST)

    if (!dev) {
      this.pagesManifest = require(pagesManifestPath)
    }

    this.customRoutes = this.getCustomRoutes()
    this.router = new Router(this.generateRoutes())
    this.setAssetPrefix(assetPrefix)

    this.incrementalCache = new IncrementalCache({
      dev,
      distDir: this.distDir,
      pagesDir: join(
        this.distDir,
        this._isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY,
        'pages'
      ),
      locales: this.nextConfig.i18n?.locales,
      max: this.nextConfig.experimental.isrMemoryCacheSize,
      flushToDisk: !minimalMode && this.nextConfig.experimental.isrFlushToDisk,
    })
    this.responseCache = new ResponseCache(this.incrementalCache)

    /**
     * This sets environment variable to be used at the time of SSR by head.tsx.
     * Using this from process.env allows targeting both serverless and SSR by calling
     * `process.env.__NEXT_OPTIMIZE_IMAGES`.
     * TODO(atcastle@): Remove this when experimental.optimizeImages are being cleaned up.
     */
    if (this.renderOpts.optimizeFonts) {
      process.env.__NEXT_OPTIMIZE_FONTS = JSON.stringify(true)
    }
    if (this.renderOpts.optimizeImages) {
      process.env.__NEXT_OPTIMIZE_IMAGES = JSON.stringify(true)
    }
    if (this.renderOpts.optimizeCss) {
      process.env.__NEXT_OPTIMIZE_CSS = JSON.stringify(true)
    }
  }

  public logError(err: Error): void {
    if (this.quiet) return
    console.error(err)
  }

  private async handleRequest(
    req: IncomingMessage,
    res: ServerResponse,
    parsedUrl?: UrlWithParsedQuery
  ): Promise<void> {
    const urlParts = (req.url || '').split('?')
    const urlNoQuery = urlParts[0]

    if (urlNoQuery?.match(/(\\|\/\/)/)) {
      const cleanUrl = normalizeRepeatedSlashes(req.url!)
      res.setHeader('Location', cleanUrl)
      res.setHeader('Refresh', `0;url=${cleanUrl}`)
      res.statusCode = 308
      res.end(cleanUrl)
      return
    }

    setLazyProp({ req: req as any }, 'cookies', getCookieParser(req.headers))

    // Parse url if parsedUrl not provided
    if (!parsedUrl || typeof parsedUrl !== 'object') {
      const url: any = req.url
      parsedUrl = parseUrl(url, true)
    }
    const { basePath, i18n } = this.nextConfig

    // Parse the querystring ourselves if the user doesn't handle querystring parsing
    if (typeof parsedUrl.query === 'string') {
      parsedUrl.query = parseQs(parsedUrl.query)
    }
    ;(req as any).__NEXT_INIT_QUERY = Object.assign({}, parsedUrl.query)

    const url = parseNextUrl({
      headers: req.headers,
      nextConfig: this.nextConfig,
      url: req.url?.replace(/^\/+/, '/'),
    })

    if (url.basePath) {
      ;(req as any)._nextHadBasePath = true
      req.url = req.url!.replace(basePath, '') || '/'
    }

    if (
      this.minimalMode &&
      req.headers['x-matched-path'] &&
      typeof req.headers['x-matched-path'] === 'string'
    ) {
      const reqUrlIsDataUrl = req.url?.includes('/_next/data')
      const matchedPathIsDataUrl =
        req.headers['x-matched-path']?.includes('/_next/data')
      const isDataUrl = reqUrlIsDataUrl || matchedPathIsDataUrl

      let parsedPath = parseUrl(
        isDataUrl ? req.url! : (req.headers['x-matched-path'] as string),
        true
      )
      const { pathname, query } = parsedPath
      let matchedPathname = pathname as string

      let matchedPathnameNoExt = isDataUrl
        ? matchedPathname.replace(/\.json$/, '')
        : matchedPathname

      if (i18n) {
        const localePathResult = normalizeLocalePath(
          matchedPathname || '/',
          i18n.locales
        )

        if (localePathResult.detectedLocale) {
          parsedUrl.query.__nextLocale = localePathResult.detectedLocale
        }
      }

      if (isDataUrl) {
        matchedPathname = denormalizePagePath(matchedPathname)
        matchedPathnameNoExt = denormalizePagePath(matchedPathnameNoExt)
      }

      const pageIsDynamic = isDynamicRoute(matchedPathnameNoExt)
      const combinedRewrites: Rewrite[] = []

      combinedRewrites.push(...this.customRoutes.rewrites.beforeFiles)
      combinedRewrites.push(...this.customRoutes.rewrites.afterFiles)
      combinedRewrites.push(...this.customRoutes.rewrites.fallback)

      const utils = getUtils({
        pageIsDynamic,
        page: matchedPathnameNoExt,
        i18n: this.nextConfig.i18n,
        basePath: this.nextConfig.basePath,
        rewrites: combinedRewrites,
      })

      utils.handleRewrites(req, parsedUrl)

      // interpolate dynamic params and normalize URL if needed
      if (pageIsDynamic) {
        let params: ParsedUrlQuery | false = {}

        Object.assign(parsedUrl.query, query)
        const paramsResult = utils.normalizeDynamicRouteParams(parsedUrl.query)

        if (paramsResult.hasValidParams) {
          params = paramsResult.params
        } else if (req.headers['x-now-route-matches']) {
          const opts: Record<string, string> = {}
          params = utils.getParamsFromRouteMatches(
            req,
            opts,
            (parsedUrl.query.__nextLocale as string | undefined) || ''
          )

          if (opts.locale) {
            parsedUrl.query.__nextLocale = opts.locale
          }
        } else {
          params = utils.dynamicRouteMatcher!(matchedPathnameNoExt)
        }

        if (params) {
          params = utils.normalizeDynamicRouteParams(params).params

          matchedPathname = utils.interpolateDynamicPath(
            matchedPathname,
            params
          )
          req.url = utils.interpolateDynamicPath(req.url!, params)
        }

        if (reqUrlIsDataUrl && matchedPathIsDataUrl) {
          req.url = formatUrl({
            ...parsedPath,
            pathname: matchedPathname,
          })
        }

        Object.assign(parsedUrl.query, params)
        utils.normalizeVercelUrl(req, true)
      }

      parsedUrl.pathname = `${basePath || ''}${
        matchedPathname === '/' && basePath ? '' : matchedPathname
      }`
    }

    ;(req as any).__nextHadTrailingSlash = url.locale?.trailingSlash
    if (url.locale?.domain) {
      ;(req as any).__nextIsLocaleDomain = true
    }

    if (url.locale?.path.detectedLocale) {
      req.url = formatUrl(url)
      ;(req as any).__nextStrippedLocale = true
      if (url.pathname === '/api' || url.pathname.startsWith('/api/')) {
        return this.render404(req, res, parsedUrl)
      }
    }

    if (!this.minimalMode || !parsedUrl.query.__nextLocale) {
      if (url?.locale?.locale) {
        parsedUrl.query.__nextLocale = url.locale.locale
      }
    }

    if (url?.locale?.defaultLocale) {
      parsedUrl.query.__nextDefaultLocale = url.locale.defaultLocale
    }

    if (url.locale?.redirect) {
      res.setHeader('Location', url.locale.redirect)
      res.statusCode = TEMPORARY_REDIRECT_STATUS
      res.end()
      return
    }

    res.statusCode = 200
    try {
      return await this.run(req, res, parsedUrl)
    } catch (err) {
      if (this.minimalMode || this.renderOpts.dev) {
        throw err
      }
      this.logError(isError(err) ? err : new Error(err + ''))
      res.statusCode = 500
      res.end('Internal Server Error')
    }
  }

  public getRequestHandler() {
    return this.handleRequest.bind(this)
  }

  public setAssetPrefix(prefix?: string): void {
    this.renderOpts.assetPrefix = prefix ? prefix.replace(/\/$/, '') : ''
  }

  // Backwards compatibility
  public async prepare(): Promise<void> {}

  // Backwards compatibility
  protected async close(): Promise<void> {}

  protected setImmutableAssetCacheControl(res: ServerResponse): void {
    res.setHeader('Cache-Control', 'public, max-age=31536000, immutable')
  }

  protected getCustomRoutes(): CustomRoutes {
    const customRoutes = require(join(this.distDir, ROUTES_MANIFEST))
    let rewrites: CustomRoutes['rewrites']

    // rewrites can be stored as an array when an array is
    // returned in next.config.js so massage them into
    // the expected object format
    if (Array.isArray(customRoutes.rewrites)) {
      rewrites = {
        beforeFiles: [],
        afterFiles: customRoutes.rewrites,
        fallback: [],
      }
    } else {
      rewrites = customRoutes.rewrites
    }
    return Object.assign(customRoutes, { rewrites })
  }

  private _cachedPreviewManifest: PrerenderManifest | undefined
  protected getPrerenderManifest(): PrerenderManifest {
    if (this._cachedPreviewManifest) {
      return this._cachedPreviewManifest
    }
    const manifest = require(join(this.distDir, PRERENDER_MANIFEST))
    return (this._cachedPreviewManifest = manifest)
  }

  protected getPreviewProps(): __ApiPreviewProps {
    return this.getPrerenderManifest().preview
  }

  protected generateRoutes(): {
    basePath: string
    headers: Route[]
    rewrites: {
      beforeFiles: Route[]
      afterFiles: Route[]
      fallback: Route[]
    }
    fsRoutes: Route[]
    redirects: Route[]
    catchAllRoute: Route
    pageChecker: PageChecker
    useFileSystemPublicRoutes: boolean
    dynamicRoutes: DynamicRoutes | undefined
    locales: string[]
  } {
    const server: Server = this
    const publicRoutes = fs.existsSync(this.publicDir)
      ? this.generatePublicRoutes()
      : []

    const staticFilesRoute = this.hasStaticDir
      ? [
          {
            // It's very important to keep this route's param optional.
            // (but it should support as many params as needed, separated by '/')
            // Otherwise this will lead to a pretty simple DOS attack.
            // See more: https://github.com/vercel/next.js/issues/2617
            match: route('/static/:path*'),
            name: 'static catchall',
            fn: async (req, res, params, parsedUrl) => {
              const p = join(this.dir, 'static', ...params.path)
              await this.serveStatic(req, res, p, parsedUrl)
              return {
                finished: true,
              }
            },
          } as Route,
        ]
      : []

    const fsRoutes: Route[] = [
      {
        match: route('/_next/static/:path*'),
        type: 'route',
        name: '_next/static catchall',
        fn: async (req, res, params, parsedUrl) => {
          // make sure to 404 for /_next/static itself
          if (!params.path) {
            await this.render404(req, res, parsedUrl)
            return {
              finished: true,
            }
          }

          if (
            params.path[0] === CLIENT_STATIC_FILES_RUNTIME ||
            params.path[0] === 'chunks' ||
            params.path[0] === 'css' ||
            params.path[0] === 'image' ||
            params.path[0] === 'media' ||
            params.path[0] === this.buildId ||
            params.path[0] === 'pages' ||
            params.path[1] === 'pages'
          ) {
            this.setImmutableAssetCacheControl(res)
          }
          const p = join(
            this.distDir,
            CLIENT_STATIC_FILES_PATH,
            ...(params.path || [])
          )
          await this.serveStatic(req, res, p, parsedUrl)
          return {
            finished: true,
          }
        },
      },
      {
        match: route('/_next/data/:path*'),
        type: 'route',
        name: '_next/data catchall',
        fn: async (req, res, params, _parsedUrl) => {
          // Make sure to 404 for /_next/data/ itself and
          // we also want to 404 if the buildId isn't correct
          if (!params.path || params.path[0] !== this.buildId) {
            await this.render404(req, res, _parsedUrl)
            return {
              finished: true,
            }
          }
          // remove buildId from URL
          params.path.shift()

          // show 404 if it doesn't end with .json
          if (!params.path[params.path.length - 1].endsWith('.json')) {
            await this.render404(req, res, _parsedUrl)
            return {
              finished: true,
            }
          }

          // re-create page's pathname
          let pathname = `/${params.path.join('/')}`
          pathname = getRouteFromAssetPath(pathname, '.json')

          const { i18n } = this.nextConfig

          if (i18n) {
            const { host } = req?.headers || {}
            // remove port from host and remove port if present
            const hostname = host?.split(':')[0].toLowerCase()
            const localePathResult = normalizeLocalePath(pathname, i18n.locales)
            const { defaultLocale } =
              detectDomainLocale(i18n.domains, hostname) || {}

            let detectedLocale = ''

            if (localePathResult.detectedLocale) {
              pathname = localePathResult.pathname
              detectedLocale = localePathResult.detectedLocale
            }

            _parsedUrl.query.__nextLocale = detectedLocale!
            _parsedUrl.query.__nextDefaultLocale =
              defaultLocale || i18n.defaultLocale

            if (!detectedLocale) {
              _parsedUrl.query.__nextLocale =
                _parsedUrl.query.__nextDefaultLocale
              await this.render404(req, res, _parsedUrl)
              return { finished: true }
            }
          }

          const parsedUrl = parseUrl(pathname, true)

          await this.render(
            req,
            res,
            pathname,
            { ..._parsedUrl.query, _nextDataReq: '1' },
            parsedUrl
          )
          return {
            finished: true,
          }
        },
      },
      {
        match: route('/_next/image'),
        type: 'route',
        name: '_next/image catchall',
        fn: (req, res, _params, parsedUrl) => {
          if (this.minimalMode) {
            res.statusCode = 400
            res.end('Bad Request')
            return {
              finished: true,
            }
          }
          const { imageOptimizer } =
            require('./image-optimizer') as typeof import('./image-optimizer')

          return imageOptimizer(
            server,
            req,
            res,
            parsedUrl,
            server.nextConfig,
            server.distDir,
            this.renderOpts.dev
          )
        },
      },
      {
        match: route('/_next/:path*'),
        type: 'route',
        name: '_next catchall',
        // This path is needed because `render()` does a check for `/_next` and the calls the routing again
        fn: async (req, res, _params, parsedUrl) => {
          await this.render404(req, res, parsedUrl)
          return {
            finished: true,
          }
        },
      },
      ...publicRoutes,
      ...staticFilesRoute,
    ]

    const restrictedRedirectPaths = ['/_next'].map((p) =>
      this.nextConfig.basePath ? `${this.nextConfig.basePath}${p}` : p
    )

    const getCustomRoute = (
      r: Rewrite | Redirect | Header,
      type: RouteType
    ) => {
      const match = getCustomRouteMatcher(
        r.source,
        !(r as any).internal
          ? (regex: string) =>
              modifyRouteRegex(
                regex,
                type === 'redirect' ? restrictedRedirectPaths : undefined
              )
          : undefined
      )

      return {
        ...r,
        type,
        match,
        name: type,
        fn: async (_req, _res, _params, _parsedUrl) => ({ finished: false }),
      } as Route & Rewrite & Header
    }

    // Headers come very first
    const headers = this.minimalMode
      ? []
      : this.customRoutes.headers.map((r) => {
          const headerRoute = getCustomRoute(r, 'header')
          return {
            match: headerRoute.match,
            has: headerRoute.has,
            type: headerRoute.type,
            name: `${headerRoute.type} ${headerRoute.source} header route`,
            fn: async (_req, res, params, _parsedUrl) => {
              const hasParams = Object.keys(params).length > 0

              for (const header of (headerRoute as Header).headers) {
                let { key, value } = header
                if (hasParams) {
                  key = compileNonPath(key, params)
                  value = compileNonPath(value, params)
                }
                res.setHeader(key, value)
              }
              return { finished: false }
            },
          } as Route
        })

    // since initial query values are decoded by querystring.parse
    // we need to re-encode them here but still allow passing through
    // values from rewrites/redirects
    const stringifyQuery = (req: IncomingMessage, query: ParsedUrlQuery) => {
      const initialQueryValues = Object.values((req as any).__NEXT_INIT_QUERY)

      return stringifyQs(query, undefined, undefined, {
        encodeURIComponent(value) {
          if (initialQueryValues.some((val) => val === value)) {
            return encodeURIComponent(value)
          }
          return value
        },
      })
    }

    const redirects = this.minimalMode
      ? []
      : this.customRoutes.redirects.map((redirect) => {
          const redirectRoute = getCustomRoute(redirect, 'redirect')
          return {
            internal: redirectRoute.internal,
            type: redirectRoute.type,
            match: redirectRoute.match,
            has: redirectRoute.has,
            statusCode: redirectRoute.statusCode,
            name: `Redirect route ${redirectRoute.source}`,
            fn: async (req, res, params, parsedUrl) => {
              const { parsedDestination } = prepareDestination(
                redirectRoute.destination,
                params,
                parsedUrl.query,
                false
              )

              const { query } = parsedDestination
              delete (parsedDestination as any).query

              parsedDestination.search = stringifyQuery(req, query)

              let updatedDestination = formatUrl(parsedDestination)

              if (updatedDestination.startsWith('/')) {
                updatedDestination =
                  normalizeRepeatedSlashes(updatedDestination)
              }

              res.setHeader('Location', updatedDestination)
              res.statusCode = getRedirectStatus(redirectRoute as Redirect)

              // Since IE11 doesn't support the 308 header add backwards
              // compatibility using refresh header
              if (res.statusCode === 308) {
                res.setHeader('Refresh', `0;url=${updatedDestination}`)
              }

              res.end(updatedDestination)
              return {
                finished: true,
              }
            },
          } as Route
        })

    const buildRewrite = (rewrite: Rewrite, check = true) => {
      const rewriteRoute = getCustomRoute(rewrite, 'rewrite')
      return {
        ...rewriteRoute,
        check,
        type: rewriteRoute.type,
        name: `Rewrite route ${rewriteRoute.source}`,
        match: rewriteRoute.match,
        fn: async (req, res, params, parsedUrl) => {
          const { newUrl, parsedDestination } = prepareDestination(
            rewriteRoute.destination,
            params,
            parsedUrl.query,
            true
          )

          // external rewrite, proxy it
          if (parsedDestination.protocol) {
            const { query } = parsedDestination
            delete (parsedDestination as any).query
            parsedDestination.search = stringifyQuery(req, query)

            const target = formatUrl(parsedDestination)
            const proxy = new Proxy({
              target,
              changeOrigin: true,
              ignorePath: true,
              xfwd: true,
              proxyTimeout: 30_000, // limit proxying to 30 seconds
            })

            await new Promise((proxyResolve, proxyReject) => {
              let finished = false

              proxy.on('proxyReq', (proxyReq) => {
                proxyReq.on('close', () => {
                  if (!finished) {
                    finished = true
                    proxyResolve(true)
                  }
                })
              })
              proxy.on('error', (err) => {
                if (!finished) {
                  finished = true
                  proxyReject(err)
                }
              })
              proxy.web(req, res)
            })

            return {
              finished: true,
            }
          }
          ;(req as any)._nextRewroteUrl = newUrl
          ;(req as any)._nextDidRewrite =
            (req as any)._nextRewroteUrl !== req.url

          return {
            finished: false,
            pathname: newUrl,
            query: parsedDestination.query,
          }
        },
      } as Route
    }

    let beforeFiles: Route[] = []
    let afterFiles: Route[] = []
    let fallback: Route[] = []

    if (!this.minimalMode) {
      if (Array.isArray(this.customRoutes.rewrites)) {
        afterFiles = this.customRoutes.rewrites.map((r) => buildRewrite(r))
      } else {
        beforeFiles = this.customRoutes.rewrites.beforeFiles.map((r) =>
          buildRewrite(r, false)
        )
        afterFiles = this.customRoutes.rewrites.afterFiles.map((r) =>
          buildRewrite(r)
        )
        fallback = this.customRoutes.rewrites.fallback.map((r) =>
          buildRewrite(r)
        )
      }
    }

    const catchAllRoute: Route = {
      match: route('/:path*'),
      type: 'route',
      name: 'Catchall render',
      fn: async (req, res, _params, parsedUrl) => {
        let { pathname, query } = parsedUrl
        if (!pathname) {
          throw new Error('pathname is undefined')
        }

        // next.js core assumes page path without trailing slash
        pathname = removePathTrailingSlash(pathname)

        if (this.nextConfig.i18n) {
          const localePathResult = normalizeLocalePath(
            pathname,
            this.nextConfig.i18n?.locales
          )

          if (localePathResult.detectedLocale) {
            pathname = localePathResult.pathname
            parsedUrl.query.__nextLocale = localePathResult.detectedLocale
          }
        }
        const bubbleNoFallback = !!query._nextBubbleNoFallback

        if (pathname === '/api' || pathname.startsWith('/api/')) {
          delete query._nextBubbleNoFallback

          const handled = await this.handleApiRequest(
            req as NextApiRequest,
            res as NextApiResponse,
            pathname,
            query
          )
          if (handled) {
            return { finished: true }
          }
        }

        try {
          await this.render(req, res, pathname, query, parsedUrl)

          return {
            finished: true,
          }
        } catch (err) {
          if (err instanceof NoFallbackError && bubbleNoFallback) {
            return {
              finished: false,
            }
          }
          throw err
        }
      },
    }

    const { useFileSystemPublicRoutes } = this.nextConfig

    if (useFileSystemPublicRoutes) {
      this.dynamicRoutes = this.getDynamicRoutes()
    }

    return {
      headers,
      fsRoutes,
      rewrites: {
        beforeFiles,
        afterFiles,
        fallback,
      },
      redirects,
      catchAllRoute,
      useFileSystemPublicRoutes,
      dynamicRoutes: this.dynamicRoutes,
      basePath: this.nextConfig.basePath,
      pageChecker: this.hasPage.bind(this),
      locales: this.nextConfig.i18n?.locales || [],
    }
  }

  private async getPagePath(
    pathname: string,
    locales?: string[]
  ): Promise<string> {
    return getPagePath(
      pathname,
      this.distDir,
      this._isLikeServerless,
      this.renderOpts.dev,
      locales
    )
  }

  protected async hasPage(pathname: string): Promise<boolean> {
    let found = false
    try {
      found = !!(await this.getPagePath(
        pathname,
        this.nextConfig.i18n?.locales
      ))
    } catch (_) {}

    return found
  }

  protected async _beforeCatchAllRender(
    _req: IncomingMessage,
    _res: ServerResponse,
    _params: Params,
    _parsedUrl: UrlWithParsedQuery
  ): Promise<boolean> {
    return false
  }

  // Used to build API page in development
  protected async ensureApiPage(_pathname: string): Promise<void> {}

  /**
   * Resolves `API` request, in development builds on demand
   * @param req http request
   * @param res http response
   * @param pathname path of request
   */
  private async handleApiRequest(
    req: IncomingMessage,
    res: ServerResponse,
    pathname: string,
    query: ParsedUrlQuery
  ): Promise<boolean> {
    let page = pathname
    let params: Params | boolean = false
    let pageFound = await this.hasPage(page)

    if (!pageFound && this.dynamicRoutes) {
      for (const dynamicRoute of this.dynamicRoutes) {
        params = dynamicRoute.match(pathname)
        if (dynamicRoute.page.startsWith('/api') && params) {
          page = dynamicRoute.page
          pageFound = true
          break
        }
      }
    }

    if (!pageFound) {
      return false
    }
    // Make sure the page is built before getting the path
    // or else it won't be in the manifest yet
    await this.ensureApiPage(page)

    let builtPagePath
    try {
      builtPagePath = await this.getPagePath(page)
    } catch (err) {
      if (isError(err) && err.code === 'ENOENT') {
        return false
      }
      throw err
    }

    const pageModule = await require(builtPagePath)
    query = { ...query, ...params }

    delete query.__nextLocale
    delete query.__nextDefaultLocale

    if (!this.renderOpts.dev && this._isLikeServerless) {
      if (typeof pageModule.default === 'function') {
        prepareServerlessUrl(req, query)
        await pageModule.default(req, res)
        return true
      }
    }

    await apiResolver(
      req,
      res,
      query,
      pageModule,
      this.renderOpts.previewProps,
      this.minimalMode,
      this.renderOpts.dev,
      page
    )
    return true
  }

  protected generatePublicRoutes(): Route[] {
    const publicFiles = new Set(
      recursiveReadDirSync(this.publicDir).map((p) =>
        encodeURI(p.replace(/\\/g, '/'))
      )
    )

    return [
      {
        match: route('/:path*'),
        name: 'public folder catchall',
        fn: async (req, res, params, parsedUrl) => {
          const pathParts: string[] = params.path || []
          const { basePath } = this.nextConfig

          // if basePath is defined require it be present
          if (basePath) {
            const basePathParts = basePath.split('/')
            // remove first empty value
            basePathParts.shift()

            if (
              !basePathParts.every((part: string, idx: number) => {
                return part === pathParts[idx]
              })
            ) {
              return { finished: false }
            }

            pathParts.splice(0, basePathParts.length)
          }

          let path = `/${pathParts.join('/')}`

          if (!publicFiles.has(path)) {
            // In `next-dev-server.ts`, we ensure encoded paths match
            // decoded paths on the filesystem. So we need do the
            // opposite here: make sure decoded paths match encoded.
            path = encodeURI(path)
          }

          if (publicFiles.has(path)) {
            await this.serveStatic(
              req,
              res,
              join(this.publicDir, ...pathParts),
              parsedUrl
            )
            return {
              finished: true,
            }
          }
          return {
            finished: false,
          }
        },
      } as Route,
    ]
  }

  protected getDynamicRoutes(): Array<DynamicRouteItem> {
    const addedPages = new Set<string>()

    return getSortedRoutes(
      Object.keys(this.pagesManifest!).map(
        (page) =>
          normalizeLocalePath(page, this.nextConfig.i18n?.locales).pathname
      )
    )
      .map((page) => {
        if (addedPages.has(page) || !isDynamicRoute(page)) return null
        addedPages.add(page)
        return {
          page,
          match: getRouteMatcher(getRouteRegex(page)),
        }
      })
      .filter((item): item is DynamicRouteItem => Boolean(item))
  }

  private handleCompression(req: IncomingMessage, res: ServerResponse): void {
    if (this.compression) {
      this.compression(req, res, () => {})
    }
  }

  protected async run(
    req: IncomingMessage,
    res: ServerResponse,
    parsedUrl: UrlWithParsedQuery
  ): Promise<void> {
    this.handleCompression(req, res)

    try {
      const matched = await this.router.execute(req, res, parsedUrl)
      if (matched) {
        return
      }
    } catch (err) {
      if (err instanceof DecodeError) {
        res.statusCode = 400
        return this.renderError(null, req, res, '/_error', {})
      }
      throw err
    }

    await this.render404(req, res, parsedUrl)
  }

  private async pipe(
    fn: (ctx: RequestContext) => Promise<ResponsePayload | null>,
    partialContext: {
      req: IncomingMessage
      res: ServerResponse
      pathname: string
      query: ParsedUrlQuery
    }
  ): Promise<void> {
    const userAgent = partialContext.req.headers['user-agent']
    const ctx = {
      ...partialContext,
      renderOpts: {
        ...this.renderOpts,
        supportsDynamicHTML: userAgent ? !isBot(userAgent) : false,
      },
    } as const
    const payload = await fn(ctx)
    if (payload === null) {
      return
    }
    const { req, res } = ctx
    const { body, type, revalidateOptions } = payload
    if (!isResSent(res)) {
      const { generateEtags, poweredByHeader, dev } = this.renderOpts
      if (dev) {
        // In dev, we should not cache pages for any reason.
        res.setHeader('Cache-Control', 'no-store, must-revalidate')
      }
      return sendRenderResult({
        req,
        res,
        result: body,
        type,
        generateEtags,
        poweredByHeader,
        options: revalidateOptions,
      })
    }
  }

  private async getStaticHTML(
    fn: (ctx: RequestContext) => Promise<ResponsePayload | null>,
    partialContext: {
      req: IncomingMessage
      res: ServerResponse
      pathname: string
      query: ParsedUrlQuery
    }
  ): Promise<string | null> {
    const payload = await fn({
      ...partialContext,
      renderOpts: {
        ...this.renderOpts,
        supportsDynamicHTML: false,
      },
    })
    if (payload === null) {
      return null
    }
    return payload.body.toUnchunkedString()
  }

  public async render(
    req: IncomingMessage,
    res: ServerResponse,
    pathname: string,
    query: ParsedUrlQuery = {},
    parsedUrl?: UrlWithParsedQuery
  ): Promise<void> {
    if (!pathname.startsWith('/')) {
      console.warn(
        `Cannot render page with path "${pathname}", did you mean "/${pathname}"?. See more info here: https://nextjs.org/docs/messages/render-no-starting-slash`
      )
    }

    if (
      this.renderOpts.customServer &&
      pathname === '/index' &&
      !(await this.hasPage('/index'))
    ) {
      // maintain backwards compatibility for custom server
      // (see custom-server integration tests)
      pathname = '/'
    }

    const url: any = req.url

    // we allow custom servers to call render for all URLs
    // so check if we need to serve a static _next file or not.
    // we don't modify the URL for _next/data request but still
    // call render so we special case this to prevent an infinite loop
    if (
      !this.minimalMode &&
      !query._nextDataReq &&
      (url.match(/^\/_next\//) ||
        (this.hasStaticDir && url.match(/^\/static\//)))
    ) {
      return this.handleRequest(req, res, parsedUrl)
    }

    // Custom server users can run `app.render()` which needs compression.
    if (this.renderOpts.customServer) {
      this.handleCompression(req, res)
    }

    if (isBlockedPage(pathname)) {
      return this.render404(req, res, parsedUrl)
    }

    return this.pipe((ctx) => this.renderToResponse(ctx), {
      req,
      res,
      pathname,
      query,
    })
  }

  protected async findPageComponents(
    pathname: string,
    query: ParsedUrlQuery = {},
    params: Params | null = null
  ): Promise<FindComponentsResult | null> {
    let paths = [
      // try serving a static AMP version first
      query.amp ? normalizePagePath(pathname) + '.amp' : null,
      pathname,
    ].filter(Boolean)

    if (query.__nextLocale) {
      paths = [
        ...paths.map(
          (path) => `/${query.__nextLocale}${path === '/' ? '' : path}`
        ),
        ...paths,
      ]
    }

    for (const pagePath of paths) {
      try {
        const components = await loadComponents(
          this.distDir,
          pagePath!,
          !this.renderOpts.dev && this._isLikeServerless
        )

        if (
          query.__nextLocale &&
          typeof components.Component === 'string' &&
          !pagePath?.startsWith(`/${query.__nextLocale}`)
        ) {
          // if loading an static HTML file the locale is required
          // to be present since all HTML files are output under their locale
          continue
        }

        return {
          components,
          query: {
            ...(components.getStaticProps
              ? {
                  amp: query.amp,
                  _nextDataReq: query._nextDataReq,
                  __nextLocale: query.__nextLocale,
                  __nextDefaultLocale: query.__nextDefaultLocale,
                }
              : query),
            ...(params || {}),
          },
        }
      } catch (err) {
        if (isError(err) && err.code !== 'ENOENT') throw err
      }
    }
    return null
  }

  protected async getStaticPaths(pathname: string): Promise<{
    staticPaths: string[] | undefined
    fallbackMode: 'static' | 'blocking' | false
  }> {
    // `staticPaths` is intentionally set to `undefined` as it should've
    // been caught when checking disk data.
    const staticPaths = undefined

    // Read whether or not fallback should exist from the manifest.
    const fallbackField =
      this.getPrerenderManifest().dynamicRoutes[pathname].fallback

    return {
      staticPaths,
      fallbackMode:
        typeof fallbackField === 'string'
          ? 'static'
          : fallbackField === null
          ? 'blocking'
          : false,
    }
  }

  private async renderToResponseWithComponents(
    { req, res, pathname, renderOpts: opts }: RequestContext,
    { components, query }: FindComponentsResult
  ): Promise<ResponsePayload | null> {
    const is404Page = pathname === '/404'
    const is500Page = pathname === '/500'

    const isLikeServerless =
      typeof components.ComponentMod === 'object' &&
      typeof (components.ComponentMod as any).renderReqToHTML === 'function'
    const isSSG = !!components.getStaticProps
    const hasServerProps = !!components.getServerSideProps
    const hasStaticPaths = !!components.getStaticPaths
    const hasGetInitialProps = !!(components.Component as any).getInitialProps

    // Toggle whether or not this is a Data request
    const isDataReq = !!query._nextDataReq && (isSSG || hasServerProps)
    delete query._nextDataReq

    // we need to ensure the status code if /404 is visited directly
    if (is404Page && !isDataReq) {
      res.statusCode = 404
    }

    // ensure correct status is set when visiting a status page
    // directly e.g. /500
    if (STATIC_STATUS_PAGES.includes(pathname)) {
      res.statusCode = parseInt(pathname.substr(1), 10)
    }

    // handle static page
    if (typeof components.Component === 'string') {
      return {
        type: 'html',
        // TODO: Static pages should be serialized as RenderResult
        body: RenderResult.fromStatic(components.Component),
      }
    }

    if (!query.amp) {
      delete query.amp
    }

    if (opts.supportsDynamicHTML === true) {
      // Disable dynamic HTML in cases that we know it won't be generated,
      // so that we can continue generating a cache key when possible.
      opts.supportsDynamicHTML =
        !isSSG &&
        !isLikeServerless &&
        !query.amp &&
        !this.minimalMode &&
        typeof components.Document?.getInitialProps !== 'function'
    }

    const locale = query.__nextLocale as string
    const defaultLocale = isSSG
      ? this.nextConfig.i18n?.defaultLocale
      : (query.__nextDefaultLocale as string)

    const { i18n } = this.nextConfig
    const locales = i18n?.locales

    let previewData: PreviewData
    let isPreviewMode = false

    if (hasServerProps || isSSG) {
      previewData = tryGetPreviewData(req, res, this.renderOpts.previewProps)
      isPreviewMode = previewData !== false
    }

    // Compute the iSSG cache key. We use the rewroteUrl since
    // pages with fallback: false are allowed to be rewritten to
    // and we need to look up the path by the rewritten path
    let urlPathname = parseUrl(req.url || '').pathname || '/'

    let resolvedUrlPathname = (req as any)._nextRewroteUrl
      ? (req as any)._nextRewroteUrl
      : urlPathname

    urlPathname = removePathTrailingSlash(urlPathname)
    resolvedUrlPathname = normalizeLocalePath(
      removePathTrailingSlash(resolvedUrlPathname),
      this.nextConfig.i18n?.locales
    ).pathname

    const stripNextDataPath = (path: string) => {
      if (path.includes(this.buildId)) {
        const splitPath = path.substring(
          path.indexOf(this.buildId) + this.buildId.length
        )

        path = denormalizePagePath(splitPath.replace(/\.json$/, ''))
      }

      if (this.nextConfig.i18n) {
        return normalizeLocalePath(path, locales).pathname
      }
      return path
    }

    const handleRedirect = (pageData: any) => {
      const redirect = {
        destination: pageData.pageProps.__N_REDIRECT,
        statusCode: pageData.pageProps.__N_REDIRECT_STATUS,
        basePath: pageData.pageProps.__N_REDIRECT_BASE_PATH,
      }
      const statusCode = getRedirectStatus(redirect)
      const { basePath } = this.nextConfig

      if (
        basePath &&
        redirect.basePath !== false &&
        redirect.destination.startsWith('/')
      ) {
        redirect.destination = `${basePath}${redirect.destination}`
      }

      if (redirect.destination.startsWith('/')) {
        redirect.destination = normalizeRepeatedSlashes(redirect.destination)
      }

      if (statusCode === PERMANENT_REDIRECT_STATUS) {
        res.setHeader('Refresh', `0;url=${redirect.destination}`)
      }

      res.statusCode = statusCode
      res.setHeader('Location', redirect.destination)
      res.end()
    }

    // remove /_next/data prefix from urlPathname so it matches
    // for direct page visit and /_next/data visit
    if (isDataReq) {
      resolvedUrlPathname = stripNextDataPath(resolvedUrlPathname)
      urlPathname = stripNextDataPath(urlPathname)
    }

    let ssgCacheKey =
      isPreviewMode || !isSSG || this.minimalMode || opts.supportsDynamicHTML
        ? null // Preview mode bypasses the cache
        : `${locale ? `/${locale}` : ''}${
            (pathname === '/' || resolvedUrlPathname === '/') && locale
              ? ''
              : resolvedUrlPathname
          }${query.amp ? '.amp' : ''}`

    if ((is404Page || is500Page) && isSSG) {
      ssgCacheKey = `${locale ? `/${locale}` : ''}${pathname}${
        query.amp ? '.amp' : ''
      }`
    }

    if (ssgCacheKey) {
      // we only encode path delimiters for path segments from
      // getStaticPaths so we need to attempt decoding the URL
      // to match against and only escape the path delimiters
      // this allows non-ascii values to be handled e.g. Japanese characters

      // TODO: investigate adding this handling for non-SSG pages so
      // non-ascii names work there also
      ssgCacheKey = ssgCacheKey
        .split('/')
        .map((seg) => {
          try {
            seg = escapePathDelimiters(decodeURIComponent(seg), true)
          } catch (_) {
            // An improperly encoded URL was provided
            throw new DecodeError('failed to decode param')
          }
          return seg
        })
        .join('/')
    }

    const doRender: () => Promise<ResponseCacheEntry | null> = async () => {
      let pageData: any
      let body: RenderResult | null
      let sprRevalidate: number | false
      let isNotFound: boolean | undefined
      let isRedirect: boolean | undefined

      // handle serverless
      if (isLikeServerless) {
        const renderResult = await (
          components.ComponentMod as any
        ).renderReqToHTML(req, res, 'passthrough', {
          locale,
          locales,
          defaultLocale,
          optimizeCss: this.renderOpts.optimizeCss,
          distDir: this.distDir,
          fontManifest: this.renderOpts.fontManifest,
          domainLocales: this.renderOpts.domainLocales,
        })

        body = renderResult.html
        pageData = renderResult.renderOpts.pageData
        sprRevalidate = renderResult.renderOpts.revalidate
        isNotFound = renderResult.renderOpts.isNotFound
        isRedirect = renderResult.renderOpts.isRedirect
      } else {
        const origQuery = parseUrl(req.url || '', true).query
        const hadTrailingSlash =
          urlPathname !== '/' && this.nextConfig.trailingSlash

        const resolvedUrl = formatUrl({
          pathname: `${resolvedUrlPathname}${hadTrailingSlash ? '/' : ''}`,
          // make sure to only add query values from original URL
          query: origQuery,
        })

        const renderOpts: RenderOpts = {
          ...components,
          ...opts,
          isDataReq,
          resolvedUrl,
          locale,
          locales,
          defaultLocale,
          // For getServerSideProps and getInitialProps we need to ensure we use the original URL
          // and not the resolved URL to prevent a hydration mismatch on
          // asPath
          resolvedAsPath:
            hasServerProps || hasGetInitialProps
              ? formatUrl({
                  // we use the original URL pathname less the _next/data prefix if
                  // present
                  pathname: `${urlPathname}${hadTrailingSlash ? '/' : ''}`,
                  query: origQuery,
                })
              : resolvedUrl,
        }

        const renderResult = await renderToHTML(
          req,
          res,
          pathname,
          query,
          renderOpts
        )

        body = renderResult
        // TODO: change this to a different passing mechanism
        pageData = (renderOpts as any).pageData
        sprRevalidate = (renderOpts as any).revalidate
        isNotFound = (renderOpts as any).isNotFound
        isRedirect = (renderOpts as any).isRedirect
      }

      let value: ResponseCacheValue | null
      if (isNotFound) {
        value = null
      } else if (isRedirect) {
        value = { kind: 'REDIRECT', props: pageData }
      } else {
        if (!body) {
          return null
        }
        value = { kind: 'PAGE', html: body, pageData }
      }
      return { revalidate: sprRevalidate, value }
    }

    const cacheEntry = await this.responseCache.get(
      ssgCacheKey,
      async (hasResolved) => {
        const isProduction = !this.renderOpts.dev
        const isDynamicPathname = isDynamicRoute(pathname)
        const didRespond = hasResolved || isResSent(res)

        let { staticPaths, fallbackMode } = hasStaticPaths
          ? await this.getStaticPaths(pathname)
          : { staticPaths: undefined, fallbackMode: false }

        if (
          fallbackMode === 'static' &&
          isBot(req.headers['user-agent'] || '')
        ) {
          fallbackMode = 'blocking'
        }

        // When we did not respond from cache, we need to choose to block on
        // rendering or return a skeleton.
        //
        // * Data requests always block.
        //
        // * Blocking mode fallback always blocks.
        //
        // * Preview mode toggles all pages to be resolved in a blocking manner.
        //
        // * Non-dynamic pages should block (though this is an impossible
        //   case in production).
        //
        // * Dynamic pages should return their skeleton if not defined in
        //   getStaticPaths, then finish the data request on the client-side.
        //
        if (
          this.minimalMode !== true &&
          fallbackMode !== 'blocking' &&
          ssgCacheKey &&
          !didRespond &&
          !isPreviewMode &&
          isDynamicPathname &&
          // Development should trigger fallback when the path is not in
          // `getStaticPaths`
          (isProduction ||
            !staticPaths ||
            !staticPaths.includes(
              // we use ssgCacheKey here as it is normalized to match the
              // encoding from getStaticPaths along with including the locale
              query.amp ? ssgCacheKey.replace(/\.amp$/, '') : ssgCacheKey
            ))
        ) {
          if (
            // In development, fall through to render to handle missing
            // getStaticPaths.
            (isProduction || staticPaths) &&
            // When fallback isn't present, abort this render so we 404
            fallbackMode !== 'static'
          ) {
            throw new NoFallbackError()
          }

          if (!isDataReq) {
            // Production already emitted the fallback as static HTML.
            if (isProduction) {
              const html = await this.incrementalCache.getFallback(
                locale ? `/${locale}${pathname}` : pathname
              )
              return {
                value: {
                  kind: 'PAGE',
                  html: RenderResult.fromStatic(html),
                  pageData: {},
                },
              }
            }
            // We need to generate the fallback on-demand for development.
            else {
              query.__nextFallback = 'true'
              if (isLikeServerless) {
                prepareServerlessUrl(req, query)
              }
              const result = await doRender()
              if (!result) {
                return null
              }
              // Prevent caching this result
              delete result.revalidate
              return result
            }
          }
        }

        const result = await doRender()
        if (!result) {
          return null
        }
        return {
          ...result,
          revalidate:
            result.revalidate !== undefined
              ? result.revalidate
              : /* default to minimum revalidate (this should be an invariant) */ 1,
        }
      }
    )

    if (!cacheEntry) {
      if (ssgCacheKey) {
        // A cache entry might not be generated if a response is written
        // in `getInitialProps` or `getServerSideProps`, but those shouldn't
        // have a cache key. If we do have a cache key but we don't end up
        // with a cache entry, then either Next.js or the application has a
        // bug that needs fixing.
        throw new Error('invariant: cache entry required but not generated')
      }
      return null
    }

    const { revalidate, value: cachedData } = cacheEntry
    const revalidateOptions: any =
      typeof revalidate !== 'undefined' &&
      (!this.renderOpts.dev || (hasServerProps && !isDataReq))
        ? {
            // When the page is 404 cache-control should not be added unless
            // we are rendering the 404 page for notFound: true which should
            // cache according to revalidate correctly
            private: isPreviewMode || (is404Page && cachedData),
            stateful: !isSSG,
            revalidate,
          }
        : undefined

    if (!cachedData) {
      if (revalidateOptions) {
        setRevalidateHeaders(res, revalidateOptions)
      }
      if (isDataReq) {
        res.statusCode = 404
        res.end('{"notFound":true}')
        return null
      } else {
        await this.render404(
          req,
          res,
          {
            pathname,
            query,
          } as UrlWithParsedQuery,
          false
        )
        return null
      }
    } else if (cachedData.kind === 'REDIRECT') {
      if (isDataReq) {
        return {
          type: 'json',
          body: RenderResult.fromStatic(JSON.stringify(cachedData.props)),
          revalidateOptions,
        }
      } else {
        await handleRedirect(cachedData.props)
        return null
      }
    } else {
      return {
        type: isDataReq ? 'json' : 'html',
        body: isDataReq
          ? RenderResult.fromStatic(JSON.stringify(cachedData.pageData))
          : cachedData.html,
        revalidateOptions,
      }
    }
  }

  private async renderToResponse(
    ctx: RequestContext
  ): Promise<ResponsePayload | null> {
    const { res, query, pathname } = ctx
    let page = pathname
    const bubbleNoFallback = !!query._nextBubbleNoFallback
    delete query._nextBubbleNoFallback

    try {
      const result = await this.findPageComponents(pathname, query)
      if (result) {
        try {
          return await this.renderToResponseWithComponents(ctx, result)
        } catch (err) {
          const isNoFallbackError = err instanceof NoFallbackError

          if (!isNoFallbackError || (isNoFallbackError && bubbleNoFallback)) {
            throw err
          }
        }
      }

      if (this.dynamicRoutes) {
        for (const dynamicRoute of this.dynamicRoutes) {
          const params = dynamicRoute.match(pathname)
          if (!params) {
            continue
          }

          const dynamicRouteResult = await this.findPageComponents(
            dynamicRoute.page,
            query,
            params
          )
          if (dynamicRouteResult) {
            try {
              page = dynamicRoute.page
              return await this.renderToResponseWithComponents(
                {
                  ...ctx,
                  pathname: dynamicRoute.page,
                  renderOpts: {
                    ...ctx.renderOpts,
                    params,
                  },
                },
                dynamicRouteResult
              )
            } catch (err) {
              const isNoFallbackError = err instanceof NoFallbackError

              if (
                !isNoFallbackError ||
                (isNoFallbackError && bubbleNoFallback)
              ) {
                throw err
              }
            }
          }
        }
      }
    } catch (error) {
      const err = isError(error) ? error : error ? new Error(error + '') : null
      if (err instanceof NoFallbackError && bubbleNoFallback) {
        throw err
      }
      if (err instanceof DecodeError) {
        res.statusCode = 400
        return await this.renderErrorToResponse(ctx, err)
      }

      res.statusCode = 500
      const isWrappedError = err instanceof WrappedBuildError
      const response = await this.renderErrorToResponse(
        ctx,
        isWrappedError ? (err as WrappedBuildError).innerError : err
      )

      if (!isWrappedError) {
        if (this.minimalMode || this.renderOpts.dev) {
          if (isError(err)) err.page = page
          throw err
        }
        this.logError(err || new Error(error + ''))
      }
      return response
    }
    res.statusCode = 404
    return this.renderErrorToResponse(ctx, null)
  }

  public async renderToHTML(
    req: IncomingMessage,
    res: ServerResponse,
    pathname: string,
    query: ParsedUrlQuery = {}
  ): Promise<string | null> {
    return this.getStaticHTML((ctx) => this.renderToResponse(ctx), {
      req,
      res,
      pathname,
      query,
    })
  }

  public async renderError(
    err: Error | null,
    req: IncomingMessage,
    res: ServerResponse,
    pathname: string,
    query: ParsedUrlQuery = {},
    setHeaders = true
  ): Promise<void> {
    if (setHeaders) {
      res.setHeader(
        'Cache-Control',
        'no-cache, no-store, max-age=0, must-revalidate'
      )
    }

    return this.pipe(
      async (ctx) => {
        const response = await this.renderErrorToResponse(ctx, err)
        if (this.minimalMode && res.statusCode === 500) {
          throw err
        }
        return response
      },
      { req, res, pathname, query }
    )
  }

  private customErrorNo404Warn = execOnce(() => {
    console.warn(
      chalk.bold.yellow(`Warning: `) +
        chalk.yellow(
          `You have added a custom /_error page without a custom /404 page. This prevents the 404 page from being auto statically optimized.\nSee here for info: https://nextjs.org/docs/messages/custom-error-no-custom-404`
        )
    )
  })

  private async renderErrorToResponse(
    ctx: RequestContext,
    _err: Error | null
  ): Promise<ResponsePayload | null> {
    const { res, query } = ctx
    let err = _err
    if (this.renderOpts.dev && !err && res.statusCode === 500) {
      err = new Error(
        'An undefined error was thrown sometime during render... ' +
          'See https://nextjs.org/docs/messages/threw-undefined'
      )
    }
    try {
      let result: null | FindComponentsResult = null

      const is404 = res.statusCode === 404
      let using404Page = false

      // use static 404 page if available and is 404 response
      if (is404) {
        result = await this.findPageComponents('/404', query)
        using404Page = result !== null
      }
      let statusPage = `/${res.statusCode}`

      if (!result && STATIC_STATUS_PAGES.includes(statusPage)) {
        result = await this.findPageComponents(statusPage, query)
      }

      if (!result) {
        result = await this.findPageComponents('/_error', query)
        statusPage = '/_error'
      }

      if (
        process.env.NODE_ENV !== 'production' &&
        !using404Page &&
        (await this.hasPage('/_error')) &&
        !(await this.hasPage('/404'))
      ) {
        this.customErrorNo404Warn()
      }

      try {
        return await this.renderToResponseWithComponents(
          {
            ...ctx,
            pathname: statusPage,
            renderOpts: {
              ...ctx.renderOpts,
              err,
            },
          },
          result!
        )
      } catch (maybeFallbackError) {
        if (maybeFallbackError instanceof NoFallbackError) {
          throw new Error('invariant: failed to render error page')
        }
        throw maybeFallbackError
      }
    } catch (error) {
      const renderToHtmlError = isError(error)
        ? error
        : error
        ? new Error(error + '')
        : null
      const isWrappedError = renderToHtmlError instanceof WrappedBuildError
      if (!isWrappedError) {
        this.logError(renderToHtmlError || new Error(error + ''))
      }
      res.statusCode = 500
      const fallbackComponents = await this.getFallbackErrorComponents()

      if (fallbackComponents) {
        return this.renderToResponseWithComponents(
          {
            ...ctx,
            pathname: '/_error',
            renderOpts: {
              ...ctx.renderOpts,
              // We render `renderToHtmlError` here because `err` is
              // already captured in the stacktrace.
              err: isWrappedError
                ? renderToHtmlError.innerError
                : renderToHtmlError,
            },
          },
          {
            query,
            components: fallbackComponents,
          }
        )
      }
      return {
        type: 'html',
        body: RenderResult.fromStatic('Internal Server Error'),
      }
    }
  }

  public async renderErrorToHTML(
    err: Error | null,
    req: IncomingMessage,
    res: ServerResponse,
    pathname: string,
    query: ParsedUrlQuery = {}
  ): Promise<string | null> {
    return this.getStaticHTML((ctx) => this.renderErrorToResponse(ctx, err), {
      req,
      res,
      pathname,
      query,
    })
  }

  protected async getFallbackErrorComponents(): Promise<LoadComponentsReturnType | null> {
    // The development server will provide an implementation for this
    return null
  }

  public async render404(
    req: IncomingMessage,
    res: ServerResponse,
    parsedUrl?: UrlWithParsedQuery,
    setHeaders = true
  ): Promise<void> {
    const url: any = req.url
    const { pathname, query } = parsedUrl ? parsedUrl : parseUrl(url, true)
    const { i18n } = this.nextConfig

    if (i18n) {
      query.__nextLocale = query.__nextLocale || i18n.defaultLocale
      query.__nextDefaultLocale =
        query.__nextDefaultLocale || i18n.defaultLocale
    }

    res.statusCode = 404
    return this.renderError(null, req, res, pathname!, query, setHeaders)
  }

  public async serveStatic(
    req: IncomingMessage,
    res: ServerResponse,
    path: string,
    parsedUrl?: UrlWithParsedQuery
  ): Promise<void> {
    if (!this.isServeableUrl(path)) {
      return this.render404(req, res, parsedUrl)
    }

    if (!(req.method === 'GET' || req.method === 'HEAD')) {
      res.statusCode = 405
      res.setHeader('Allow', ['GET', 'HEAD'])
      return this.renderError(null, req, res, path)
    }

    try {
      await serveStatic(req, res, path)
    } catch (error) {
      if (!isError(error)) throw error
      const err = error as Error & { code?: string; statusCode?: number }
      if (err.code === 'ENOENT' || err.statusCode === 404) {
        this.render404(req, res, parsedUrl)
      } else if (err.statusCode === 412) {
        res.statusCode = 412
        return this.renderError(err, req, res, path)
      } else {
        throw err
      }
    }
  }

  private _validFilesystemPathSet: Set<string> | null = null
  private getFilesystemPaths(): Set<string> {
    if (this._validFilesystemPathSet) {
      return this._validFilesystemPathSet
    }

    const pathUserFilesStatic = join(this.dir, 'static')
    let userFilesStatic: string[] = []
    if (this.hasStaticDir && fs.existsSync(pathUserFilesStatic)) {
      userFilesStatic = recursiveReadDirSync(pathUserFilesStatic).map((f) =>
        join('.', 'static', f)
      )
    }

    let userFilesPublic: string[] = []
    if (this.publicDir && fs.existsSync(this.publicDir)) {
      userFilesPublic = recursiveReadDirSync(this.publicDir).map((f) =>
        join('.', 'public', f)
      )
    }

    let nextFilesStatic: string[] = []
    nextFilesStatic = !this.minimalMode
      ? recursiveReadDirSync(join(this.distDir, 'static')).map((f) =>
          join('.', relative(this.dir, this.distDir), 'static', f)
        )
      : []

    return (this._validFilesystemPathSet = new Set<string>([
      ...nextFilesStatic,
      ...userFilesPublic,
      ...userFilesStatic,
    ]))
  }

  protected isServeableUrl(untrustedFileUrl: string): boolean {
    // This method mimics what the version of `send` we use does:
    // 1. decodeURIComponent:
    //    https://github.com/pillarjs/send/blob/0.17.1/index.js#L989
    //    https://github.com/pillarjs/send/blob/0.17.1/index.js#L518-L522
    // 2. resolve:
    //    https://github.com/pillarjs/send/blob/de073ed3237ade9ff71c61673a34474b30e5d45b/index.js#L561

    let decodedUntrustedFilePath: string
    try {
      // (1) Decode the URL so we have the proper file name
      decodedUntrustedFilePath = decodeURIComponent(untrustedFileUrl)
    } catch {
      return false
    }

    // (2) Resolve "up paths" to determine real request
    const untrustedFilePath = resolve(decodedUntrustedFilePath)

    // don't allow null bytes anywhere in the file path
    if (untrustedFilePath.indexOf('\0') !== -1) {
      return false
    }

    // Check if .next/static, static and public are in the path.
    // If not the path is not available.
    if (
      (untrustedFilePath.startsWith(join(this.distDir, 'static') + sep) ||
        untrustedFilePath.startsWith(join(this.dir, 'static') + sep) ||
        untrustedFilePath.startsWith(join(this.dir, 'public') + sep)) === false
    ) {
      return false
    }

    // Check against the real filesystem paths
    const filesystemUrls = this.getFilesystemPaths()
    const resolved = relative(this.dir, untrustedFilePath)
    return filesystemUrls.has(resolved)
  }

  protected readBuildId(): string {
    const buildIdFile = join(this.distDir, BUILD_ID_FILE)
    try {
      return fs.readFileSync(buildIdFile, 'utf8').trim()
    } catch (err) {
      if (!fs.existsSync(buildIdFile)) {
        throw new Error(
          `Could not find a production build in the '${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id`
        )
      }

      throw err
    }
  }

  protected get _isLikeServerless(): boolean {
    return isTargetLikeServerless(this.nextConfig.target)
  }
}

function prepareServerlessUrl(
  req: IncomingMessage,
  query: ParsedUrlQuery
): void {
  const curUrl = parseUrl(req.url!, true)
  req.url = formatUrl({
    ...curUrl,
    search: undefined,
    query: {
      ...curUrl.query,
      ...query,
    },
  })
}

class NoFallbackError extends Error {}

// Internal wrapper around build errors at development
// time, to prevent us from propagating or logging them
export class WrappedBuildError extends Error {
  innerError: Error

  constructor(innerError: Error) {
    super()
    this.innerError = innerError
  }
}

type ResponsePayload = {
  type: 'html' | 'json'
  body: RenderResult
  revalidateOptions?: any
}

redpajama_set_name: RedPajamaGithub


Congratulations on finding your new home! Now the fun begins – moving everything into it. Of course it seems daunting to look at all of your belongings sitting nicely in their current spot, knowing that all of it—ALL of it—needs to be boxed up and loaded into a truck. But don't worry, people have been moving from one place to another for thousands of years. You'll be able to accomplish it, too. Take a look at these five tips from moving professionals to help your move go as smoothly as possible.
Make an agenda for moving day.To keep anxiety at a minimum, create a detailed list of what needs to be accomplished at what time during moving day. For people who are selling and/or buying a home, this is especially useful to keep everything under control. Two home closings in one day can be a bit hectic, but it's done all of the time.
Pack a box of necessities. Think of everything that you are going to need right away when you get to your new home and put it on a list. Include things like paper towels, a box cutter, tape, toilet paper, tools, etc. Make sure that none of these things are packed in other boxes that will inevitably get lost in a sea of cardboard. The day before moving day, pack all of these things into a box, or better yet a clear plastic bin so you can access them right away.
Help your movers know where to put things.Of course you're going to label all of the boxes so your professional movers know to which room they go, but make things even easier by color-coding the boxes using colored tape so it's instantly obvious where they belong. You might want to even sketch up a floor plan for the house with notations of where you want the furniture to be set up. This will allow you to stay out of the way while the movers work, and they won't have to be constantly asking you where each piece of furniture goes.
Use wardrobe boxes. Wardrobe boxes are great for bulky items like comforters, blankets, and towels. Be sure not to overstuff the boxes, as lightweight items can become heavy boxes very quickly. For hanging clothes, stuffing them into garbage bags works great and makes them all ready to hang back up when you get to your new home.
Use suitcases, duffel bags, and other containers instead of boxes. To cut down on the number of boxes you'll need, and to maximize storage space, put clothing and towels in your luggage. Just throwing your luggage in the truck (or worse, a box) doesn't take advantage of using the luggage for the reason you purchased it: to transport clothing. Plus, your luggage will be easy to spot among the many boxes, so finding a towel or a blanket right after you move in will be easy.


Vintage Diamond 14k Gold Mens 3 Row Signed Band Ring Size 10. Title Vintage Diamond 14k Gold Mens 3 Row Signed Band Ring Size 10.
Described By Georgia TISS Please review all additional images below description. Description: Offering for your consideration a classic mens vintage 14k yellow gold genuine diamond ring. The ring features (105) full cut round brilliant diamonds in 3 rows with 2 additional rows of baguette diamonds. Perfect ring for him on Valentines Day.
Measurement or Weight of Gem Stones: Round- (105) 1.0mm each= 0.50ctw approx, Baguette- (16) 2.5mm x 2.0mm= 0.80ctw approx. Color Of Gemstone or Diamond: F-I. Clarity of Gemstone or Diamond: Baguette- VS1-SI1, Round- VS1-VS2. Size or length: Ring size-10, 14mm wide. Condition: Pre-owned: overall excellent condition, shows very minimal surface wear. Stamping or Factory Markings: EHC 14KT. Total weight of piece: 8.9grams.
Estimated size of package 6x2x4. Pre-owned Description: Offering for your consideration a classic mens vintage 14k yellow gold genuine diamond ring. Item: ring Gemstones: Diamond Approx. Color Of Gemstone or Diamond: F-I Clarity of Gemstone or Diamond: Baguette- VS1-SI1, Round- VS1-VS2 Mounting metal: 14k gold Approx. Size or length: Ring size-10, 14mm wide Condition: Pre-owned: overall excellent condition, shows very minimal surface wear Stamping or Factory Markings: EHC 14KT Total weight of piece: 8.9grams.
International Carriers are: Ups Standard Canada, Ups Worldwide Saver, Ups Worldwide Express. The auctions contain only what is described. Many items will be marked with serial numbers or identifying numbers items may not be accepted for return if these numbers are not present. You can count on us to be factual and have clear accurate photographs which are not "edited" to deceive. Photographs often disclose condition far better than verbiage as many people have different ideas on what terms may mean.
This is because credit cards require both a signature and tracking. CANADA, Australia, Belgium, Brazil, Croatia, Denmark, France Germany, Great Britain and Northern Ireland, Israel, Netherlands New Zealand Spain and Switzerland, Estonia, Finland, Gibraltar, Hungary, Italy, Latvia, Lithuania, Luxembourg, Malaysia, Malta, Portugal, and Singapore.
Address: Hess Fine Auctions, 1131 4th Street North, St. Vendio Images: More than just a pretty image. 150 FREE professional templates with Vendio Sales Manager. The item "Vintage Diamond 14k Gold Mens 3 Row Signed Band Ring Size 10" is in sale since Tuesday, February 07, 2017. This item is in the category "Jewelry & Watches\Men's Jewelry\Rings". The seller is "hessfineauctions" and is located in Saint Petersburg, Florida. This item can be shipped worldwide.


July 2017 – PROS Greene | Mental Health Association of Columbia-Greene Counties, Inc.
In our program, PROS at the Firehouse (AKA PROS Greene), we believe that our mission is to assist the people who come here in this "process of change" and try to foster that in all our program activities.
Participants can take up to six classes per day with a focus on a variety of recovery and wellness topics, community resources, medication and verbal therapy, peer services (nearby Water St and our own Peer Specialist) and individualized support for their own recovery journey.
The joy of our work comes from watching participants attain goals that they once thought were near impossible. From a person celebrating their first work anniversary after years of not working; to someone who has been homeless for over a year obtaining permanent housing. You can see the light in someone's eyes brighten as they realize their goals.


text:
Practice Areas Menu
Chapter 11 and 9 Representations Angle Right
Out-of-Court Restructuring Angle Right
Receiverships Angle Right
Trustee Representations Angle Right
Bankruptcy and Commercial Litigation Angle Right
Committee and Creditor Representations Angle Right
Mediation Angle Right
Close Menu Panel
Chapter 11 and 9 Representations
Out-of-Court Restructuring
Receiverships
Trustee Representations
Bankruptcy and Commercial Litigation
Committee and Creditor Representations
601 Union Street, Suite 5000, Seattle WA 98101
Richard B. Keeton
rkeeton@bskd.com
Richard Keeton offers and implements practical solutions tailored to his clients' specific needs and desired outcomes, whether through formal bankruptcy proceedings, out-of-court workouts, state court receiverships, or related litigation.
Richard Keeton, a Washington native, joined the firm in 2019. Richard represents corporate debtors, trustees, and other parties in interest in chapter 7 liquidations and chapter 11 reorganizations across a variety of industries, including healthcare, agriculture, tobacco, and hospitality. As an appellate advocate, he has briefed and argued appeals before the Ninth Circuit Court of Appeals and the Bankruptcy Appellate Panel. Richard is also a significant contributor to the firm's receivership practice.
Richard is included in the 2022 edition of Best Lawyers: Ones to Watch for his work in Bankruptcy and Creditor/Debtor Rights, Insolvency and Reorganization Law, and has been nominated by his peers as a "Rising Star" in the areas of Bankruptcy and Creditor Debtor Rights in Thompson Reuters Super Lawyers Magazine every year since 2020. Richard is currently on the Executive Board for the King County Bar Association Bankruptcy Law Section and has served on the WSBA Board of Bar Examiners since 2017.
After graduating law school, Richard clerked for the Honorable Christopher M. Alston of the United States Bankruptcy Court for the Western District of Washington, after having previously served as an extern to Bankruptcy Judge Brian D. Lynch. During law school, Richard was published in the American Bankruptcy Law Journal, a peer reviewed journal published by the National Conference of Bankruptcy Judges, and served as the editor-in-chief of his law school's Business & Bankruptcy Law Journal.
Additional Attorney Information
Education & Bar Memberships
Presentations & Awards
Hearts and Hands of Care, Inc.
Chapter 11 representation in the District of Alaska of operator of group homes and in home care with approximately 250 employees.
Robinson Tait, P.S.
Representation of Chapter 7 trustee in the liquidation of a large and complex consumer foreclosure law firm. Represent the trustee in liquidating the debtor's assets, determining the ownership for millions of dollars of sales proceeds, and recouping preference and voidable transfers.
North Cascade Trustee Services, Inc.
Representation of Chapter 7 trustee in the liquidation of a large and complex non-judicial foreclosure business. Represent the trustee in liquidating the debtor's assets and determining the ownership for millions of dollars of sales proceeds.
In re Anderson
Representation of Chapter 7 trustee in appeal of bankruptcy court's order denying the trustee's objection to the debtor's claimed homestead exemption.
In re Turner
Representation of Chapter 7 trustee in a complex individual case involving the transfer of substantial business interests and other assets into self-settled trusts.
In re Morris
Representation of Chapter 7 trustee in the administration of estate assets.
Bachelor of Arts, University of Nevada, Las Vegas, 2011
Juris Doctor, Texas Tech University, 2015
National Order of Scribes
Editor-in-Chief, Business & Bankruptcy Law Journal
Master of Laws (LL.M.), University of Washington, 2016
Washington State Bar
Admitted to practice in the:
Eastern District of Washington;
Western District of Washington;
District of Idaho; and
Ninth Circuit Court of Appeals
The New Chapter 11 for Small Businesses: A Deep Dive into the New Subchapter V, Washington State Bar Association, February 2020
Case Law Update & Local Practice Tips: Term Law Clerk Discussion of Recent Ninth Circuit Cases and a Cheat Sheet for Your Local Procedural Questions, King County Bar Association, January 2018
Best Lawyers: Ones to Watch, Bankruptcy and Creditor/Debtor Rights, Insolvency and Reorganization Law, 2022
Super Lawyers: Rising Star, Bankruptcy and Creditor Debtor Rights, 2020–2021
Executive Board Member, KCBA Bankruptcy Law Section
Board Member, WSBA Board of Bar Examiners
Volunteer Judge, University of Washington School of Law moot court competitions
American Bar Association, Business Law Section
Washington State Bar Association, Creditor Debtor Rights Section
King County Bar Association, Bankruptcy Law Section
Turnaround Management Association
Arrow Left All Attorneys
© 2020 Bush Kornfeld. All Rights Reserved. Privacy Policy | Sitemap
Web Design by efelle creative.
If you are not a current client of Bush Kornfeld LLP, please do not include any information in this email that you or someone else considers to be confidential. Bush Kornfeld LLP will not treat as confidential any unsolicited information you provide via email or otherwise. Your message will not establish an attorney-client relationship with Bush Kornfeld LLP or any lawyer at Bush Kornfeld LLP. An attorney-client relationship cannot be established until we know that doing so will not create a conflict of interest and until we reach a written agreement on the terms of representation.
I agreeDisagree

redpajama_set_name: RedPajamaCommonCrawl


CANTON – Tiffany Mitchell, RN, of Colton said that for as long as she can remember she's wanted to work in Home Health Care.
When asked why she chose this career path, Mrs. Mitchell said she wanted to be able to develop a relationship with her patients.
"I've always had an interest in home health care, even before becoming a nurse," she said, noting that in 2012 while still in high school she began working for United Helpers at Maplewood Health Care & Rehabilitation Center as an activities aide.
While still in high school and taking Health Careers at St. Lawrence-Lewis BOCES, Mrs. Mitchell even earned her CNA certification and began working per-diem as a CNA at Maplewood.
Following graduation, Mrs. Mitchell said she attended SUNY Canton, ultimately graduating in 2015 with a nursing degree and becoming a RN. She then spent approximately six months working at Maplewood as an evening supervisor, before the opportunity arose to begin her career in home health care.
Now that she's nearly two years into her career as a RN for Northern Lights, Mrs. Mitchell said she's certain she made the right choice.
"I would recommend Northern Lights to any nurses out there looking for a job," she said. "Giving people the option to recover in their homes is something that's important to me," she said, recalling an elderly gentleman, who became a patient after developing a foot ulcer.
The gentleman, with no guarantees of success, instead elected for home health care and for two years, nurses from Northern Lights came to his home to care for the wound.
"I worked with him for about a year and during that time his wound healed and we were able to discharge him," she said, adding stories like that show how rewarding a career in home health care can be.
For more information on Northern Lights Home Health Care and how you can start your career in home health care, please call (315) 714-3135, like Northern Lights on Facebook or visit www.mynorthernlights.org/employment-opportunities.
Northern Lights is owned and operated through a partnership that includes United Helpers, Canton-Potsdam Hospital, Claxton-Hepburn Medical Center and Hospice and Palliative Care of St. Lawrence Valley.


Trieste is a city with a strong international vocation boasting a strategic position in the chess board of the new Europe due to its location which, despite overlooking the sea, places it close to central-east Europe.
It is rich in culture, heir to a glorious past, born of the progressive concentration of vivacious Mediterranean, central-European and Balkan communities. With an eye toward a new Europe and a pulsing heart in the "Bel Paese" (Italy), the future of Trieste becoming a new Central European capital again looks likely: a fascinating bridge between east and west.
The tranquil, level ground cul-de-sac where our building is located stands on the hill of St. Vito; one of the seven hills of the city. The Armenian community settled in the area at the beginning of the 18th century: their beautiful church stands next to our complex. From this position, just a few minutes' walk from the city centre and promenade, you can enjoy stunning views over the city and gulf.
Trieste's strategic position makes it the first natural access to the sea, straight into the heart of Europe.
In the centre of the new Europe, Trieste is close to the lively capitals of Vienna (478km), Budapest (558km), Bratislava (540km), Ljubljana (95km), Zagreb (230km) and Belgrade (620km) as well as interesting cities such as Venice (164km), Milan (420km), Munich (700km), Klagenfurt (170km) and Zurich (685km).
The airport is 40 kilometres away and the city is well connected by motorways and rail.


text:
New luxury off-campus student housing to open for fall 2014
By Katelyn Freil, News Editor
The Depot, the latest in off-campus student housing for The University of Akron, is currently under construction and is slated to be finished in time for the 2014 fall semester.
Located on East Exchange Street, this $30 million, 624-bed housing community from student property management company Asset Campus Housing will be a go-to option for the tech-savvy student. Integrating technology was necessary, said Aaron Pechota, vice president of development for The NRP Group LLC, the developer for The Depot.
"The biggest thing that you find in focus groups is how important technology is," Pechota said. "If your shower or toilet doesn't work, it's a problem, you have to call someone to repair it and it's an inconvenience. If you can't get on your Wi-Fi on your smartphone or your laptop, that's unacceptable."
For this reason, The Depot will include a computer lab with fixed computer workstations, a conference room with projection capability for group projects, a commercial printer, high-speed internet, Wi-Fi and workstations, according to depotatakron.com.
Pechota said that the workstations are designed to be open and flexible, as opposed to the old-school study style where students are separated by dividers. This will provide more opportunities for collaboration between students.
Pechota said the goal for any project from the NRP, including The Depot, is to be the premiere property in the market with the highest level of amenities, quality and service. According to its website, the goal for Asset Campus Housing is to provide students with a way of life that will help them attain their goals.
Other amenities at The Depot include a heated pool, a mini-market on site, a game room, two fitness rooms, a concierge desk and an outdoor kitchen and grill area. According to the website, one-, two-, three- and four-bedroom floor plans are available.
Shane Riley, the general manager of The Depot Leasing Office, said roommate matching is provided for individuals if needed and is based on a survey provided when a student signs a lease.
Amenities for each room include one bathroom per bedroom, a stacked washer and dryer, a 42-inch TV and granite countertops in the kitchen.
The Depot will also offer a place for students to congregate. Pechota said that The Depot will have speakers, parties and other events for students to enjoy together.
According to Pechota, one of the main reasons this location on East Exchange Street was chosen for The Depot was its relation to both campus and downtown Akron.
"We love the fact that we're on the edge of the university and the edge of downtown," Pechota said. "Students can walk to class and they can walk down the street when they want things to do; it's just a five-minute walk anywhere they need to go."
While the position of this lot was prime, the historical aspect also played a role in its selection, as it was once a station for the Erie Railroad before becoming a storage facility for the Akron Beacon Journal.
"One of the reasons we named it The Depot is because we recognize it as an old depot train station and it is right next to the railroad, which everyone in Akron knows runs right through the middle of the city," he said. "Instead of being scared that you're right next to the railroad tracks, you embrace it and it becomes nice that you are."
In designing the building, The NRP Group decided to incorporate aspects from the original building into the construction of The Depot. One example is the use of four monument "E's" used in the courtyard, clubhouse and concierge areas to signify the Erie Railroad, according to a recent press release. Pechota said that concrete from the old building was crushed on site and is being reused, as well as ornate supports that will be used in the gas fireplace within the building.
Riley said that from what he has seen, trends like environmental awareness are important to students and in a city like Akron, the historical aspect can be just as crucial. Repurposing materials from the original building is one way developers were able to respond to those trends.
"A lot of the future residents and students enjoy that historical aspect," Riley said.
Pechota added that while there are various homey touches throughout the building, like the fireplace and more traditional games like billiards, the overall feel is more sleek and modern. He referred to this as the "Apple influence," a nod to the popular consumer electronics company, Apple Inc.
"Everybody likes things to be sleek, a little bit more modern, a little edgier," Pechota said. "So instead of just truly traditional finish, we have a much more modern feel."
Even with all of the amenities and detail put into construction of the building, Pechota said that the price of living at The Depot is right on par with the market at The University of Akron.
"The university's done a great job of making this into a real campus as opposed to just an urban commuter school," he said. "It feels like a campus and I think what we're doing really adds to that."
For those students who want to live in The Depot but don't have a roommate and can't afford a one-bedroom apartment, individual lease liability is provided. According to Riley, students can lease one bedroom in a multi-bedroom floor plan and share the common room.
Since it was announced in early August that The Depot had officially began leasing, Riley has noticed a steady wave of students coming into the office interested in touring the building. He expects the number of students showing interest to increase as the fall semester progresses.
To find out more about The Depot, visit depotatakron.com or the leasing office at 446 E. Exchange St.
Katelyn Freil, News Editor


text:
Saint-Pierre-du-Mont Airfield is an abandoned World War II military airfield which is located in the Calvados department in the Normandy region in northern France. It was one of the many instrumental airfields used to defeat Adolf Hitler's Axis powers in World War II.

Located just north of Saint-Pierre-du-Mont along the English Channel coast, it was a United States Army Air Force temporary airfield established shortly after the D-Day landings in France. The airfield was one of the first established in the liberated area of Normandy, being constructed by the IX Engineering Command, 834th Engineer Aviation Battalion.

History
Known as Advanced Landing Ground "A-1", the airfield consisted of a single  Square-Mesh Track runway. Tents were used for billeting and for support facilities; an access road was built to the existing road infrastructure; a dump for supplies, ammunition, and gasoline drums, along with a drinkable water and minimal electrical grid for communications and station lighting.

Construction of the airfield began on 7 June, the day after the initial invasion, and was completed on 8 June at 1800 hrs The airfield was completed only 2 days after the D-Day landings in France. It was pressed into service as Emergency Landing Strip 1 (ELS A-1) with a untracked (grass/dirt) runway. It served only small observation aircraft at that time. Just over 24 hours later (18:45) it had been upgraded from a Refuelling and Rearming Strip (RRS A-1) to an Advanced Landing Ground (ALG A-1), able to handle aircraft up to the C-47 transport. From 10 June 1944 an RAF Ames Type 15 GCI radar site became active at the airfield, the only survivor of three that were accidentally sent to the Normandy beaches on D-Day, instead of D-Day+3 of the invasion.

After his day trip to Normandy on June 12, General "Hap" Arnold, USAAF commander, returned to the UK from A-1.

Combat units stationed at the airfield were the 366th Fighter Group, which based P-47 Thunderbolt fighters at the field from 13 June through 5 September 1944.

The 401st Fighter Squadron (9D), [370th Fighter Group] based P-38 Lighting fighters [note bottom center of accompanying airfield photograph]
from July - August 1944.

It also housed the 2d Platoon of the 1st Air Force Clearing Station, which had landed at Omaha Beach on 16 June. The medical unit set up a field hospital just off base, which by that time would still occasionally receive incoming enemy fire, as the front line was not far away. The platoon consisted of 4 Medical Officers, 1 Dental Officer, 1 Medical Administrative Officer, 6 (female) Nurses, and 57 Enlisted Men.

The fighter aircraft flew support missions during the Allied invasion of Normandy, patrolling roads in front of the beachhead; strafing German military vehicles and dropping bombs on gun emplacements, anti-aircraft artillery and concentrations of German troops when spotted. In addition to the fighters, elements of the 416th and 322d Bomb Groups dispatched B-26 Marauder medium bombers from their bases in England to Saint-Pierre-du-Mont to attack German strong points in Normandy during the initial battles around Saint-Lô

After the Americans moved east into Central France with the advancing Allied Armies, the airfield was left un-garrisoned and used for resupply and casualty evacuation.   It was closed on 5 September 1944.

Major units assigned
 366th Fighter Group 17 June-24 August 1944
 389th (A6), 390th (B2), 391st (A8) Fighter Squadrons (P-47D)

 401st Fighter Squadron [9D], of the 370th Fighter Group [P-38] July - August 1944

Current use
After its closure by the Americans, the airfield was dismantled in September 1944 and the land returned to agricultural use. Today there is little or no physical evidence of its existence or its location.  There is a monument to the A-1 Airfield north of the D514, just to the north of Les Bergeries.

See also

 Advanced Landing Ground

References

External links

 A-1 Memorial

World War II airfields in France
Airfields of the United States Army Air Forces in France
Airports established in 1944

redpajama_set_name: RedPajamaWikipedia


Even though the presidential search is advancing, student interest and access to information is substantially low. The five recent on campus candidate interviews were the only opportunity for students to be involved with the selection process. Before these five interviews occurred, a Florida firm conducted a national search. The campus was unaware of the 25 interviews that occurred near the Philadelphia airport early this past December. The campus still does not know who those candidates were.
According to Board of Governors policy 1983-13-A, all members of the committee must keep information about the search confidential. The only information about the search that is not confidential are the campus interviews, open forums from the Florida firm in September, and emails from search committee chair Jack Wabby.
No information about the candidates came out until the last five interviews were announced.
Even now, the finalists' curricula vitae are not available, although they were presented at the campus interviews. The university's collective part in the process is over.
The closed executive search is a common practice.
At a journalism convention in the fall semester, the Keystone staff learned about secrecy in presidential searches through a Student Press Law Center presentation. According to a SPLC article, even open searches are closed until the finalists are narrowed down.
It is unclear if the search committee ever considered acting president Dr. Carlos Vargas-Aburto, who told The Keystone last August that he intended to apply. He could have been one of the final 25 candidates, but none of the committee members or Vargas, are allowed to reveal this information.
Dr. Vargas, as provost and vice president for academic and student affairs for over 11 years, is the most familiar with the university. At the beginning of the year, he was working on important academic issues such as curriculum innovation and shortages of required classes. It would have been beneficial to consider someone who is familiar with KU or Pennsylvania state schools. None of the five finalists seem to have experience with KU and only one, Dr. James Conneely, is familiar with Pennsylvania state schools.
Diversity of candidates appeared to be a problem as well. The Keystone reporters that attended the candidates' interviews found it hard to distinguish which candidate they liked best, as they often made the same points. This may be the case for other students too.
On the other hand, even the recent opportunities for the campus to find out about the process gained little interest. The Keystone reporters observed that only a few people attended the interviews. Dr. Lorrie Clemo, one of the candidates, said that it is normal for few students to show up at these interviews.
When the president is finally selected, maybe students will gain interest. The information about the selection process, however, will practically be irrelevant by that time.