Angular-RU / universal-starter

Angular 9 Universal repo with many features

Home Page:https://ssr9.gorniv.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

HTTPClient POST request not working on Angular 6 / Angular Universal

johnsken-jerry opened this issue · comments

commented

I am unable to perform POST/PUT requests
I know Angular Universal does server-side rendering so
1、Is the reason my POST requests aren't working because the view isn't being rendered in the client?
2、When post is requested, post(...).subscribe() subscribe has no callback?

create-brand.component.ts

constructor(private http: _HttpClient) {}
queryAllBrand(pagination, data) {
  this.http.post(pagination, data).subscribe(res => { // * not callback
      console.log(`this.brandListService`, {res}); 
    }, error => {
      console.log("Error", error);
    });
}

server.ts

const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
const files = fs.readdirSync(`${process.cwd()}/dist-server`);
import fetch from 'node-fetch';

win.fetch = fetch;
global['window'] = win;
window.scrollTo = function() {};
Object.defineProperty(win.document.body.style, 'transform', {
  value: () => {
    return {
      enumerable: true,
      configurable: true
    };
  },
});
global['document'] = win.document;
global['navigator'] = win.navigator;
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;

import 'localstorage-polyfill';
 
global['localStorage'] = localStorage;

global['MutationObserver'] = getMockMutationObserver();
function getMockMutationObserver() {
  return class {
    observe(node, options) {
    }
    disconnect() {
    }
    takeRecords() {
      return [];
    }
  };
}

import 'reflect-metadata';
import 'zone.js/dist/zone-node';

import * as express from 'express';
import * as morgan from 'morgan';
import * as compression from 'compression';
import * as cookieparser from 'cookie-parser';
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');

const mainFiles = files.filter(file => file.startsWith('main'));
const hash = mainFiles[0].split('.')[1];
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(`./dist-server/main.${hash}`);
import { ngExpressEngine } from '@nguniversal/express-engine';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
const PORT = process.env.PORT || 4000;
import { ROUTES } from './static.paths';


const app = express();
app.use(compression());
app.use(cookieparser());
// Morgan
app.use(morgan('dev'));
app.use(express.static(`${__dirname}/dist`));
const redirectowww = false;
const redirectohttps = false;
const wwwredirecto = false;
app.use((req, res, next) => {
  // for domain/index.html
  if (req.url === '/index.html') {
    res.redirect(301, 'http://' + req.hostname);
  }
  next();
}
);

app.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP)
  ]
}));

app.set('view engine', 'html');
app.set('views', path.join(process.cwd(),'src'));
// app.set('views', path.join(process.cwd(), 'dist'));
const angularBuildPath = path.join(__dirname, '.', 'dist');
app.get('*.*', express.static(angularBuildPath));
app.get(ROUTES, express.static(path.join(__dirname, '.', 'static')));

app.get('*', (req, res) => {
  global['navigator'] = req['headers']['user-agent'];
  const http = req.headers['x-forwarded-proto'] === undefined ? 'http' : req.headers['x-forwarded-proto'];
  // tslint:disable-next-line:no-console
  console.time(`GET: ${req.originalUrl}`);
  res.render(
    '../dist/index',
    {
      req: req,
      res: res,
      providers: [
        {
          provide: REQUEST, useValue: (req)
        },
        {
          provide: RESPONSE, useValue: (res)
        },
        {
          provide: 'ORIGIN_URL',
          useValue: (`${http}://${req.headers.host}`)
        }
      ]
    },
    (err, html) => {
      if (!!err) { throw err; }
      console.log({err})
      // tslint:disable-next-line:no-console
      console.timeEnd(`GET: ${req.originalUrl}`);
      res.send(html);
    });
    console.log(`render end`);
});

// Error handler for 404 - Page Not Found
app.use((req, res, next) => {
  let err = new Error('Not Found');
  res.status(404).json({
      status: 404,
      message: err.message,
      name: err.name
  });
});

// Error handler for all other errors
app.use((err, req, res, next)=>{
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  res.status(err.status || 500).json({
      status: 500,
      message: err.message,
      name: err.name
  });
});

app.listen(PORT, () => {
  console.log(`listening on http://localhost:${PORT}!`);
});

You should use TransferState. You can read more about it here. Also you can watch how to use requests with SSR in this file.

commented

I have callback according to the official HTTP, but when I move my project to demo, there will be no HTTP callback.
Encapsulated http.client.ts

import { TransferHttpService } from '@gorniv/ngx-transfer-http';
export class _HttpClient {
    constructor(private http: TransferHttpService) { }

    get(url: string, params?: any): Observable<any> {
        return this.http
            .get(url, {
                params: this.parseParams(params)
            })
            .catch((res) => {
                return res;
            });
    }
}

home.component.ts

import { _HttpClient } from '@core/services/http.client';
...
constructor(private http: TransferHttpService) {}
ngOnInit() {
   this.http.get(`http://xxxx.xx/searchHasAcceptTest`).subscribe((res: any) => { // not callback
      console.log(res)
    }, error => {
      console.error("Error", error);
    });
 }
...

home.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { _HttpClient } from '@core/services/http.client';
import { HomeRoutes } from './home.routing';
import { HomeComponent } from './home.component';

@NgModule({
  imports: [
    CommonModule,
    HomeRoutes,
    TranslateModule
  ],
  providers: [
    _HttpClient
  ],
  declarations: [HomeComponent]
})
export class HomeModule { }

package.json

{
  "name": "universal-demo",
  "version": "6.1.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "ssr": "npm run build:universal && npm run generate:prerender && npm run server",
    "ssr:debug": "ng build --aot=true --output-hashing=all --named-chunks=false --build-optimizer=true  && ng run universal-demo:server:dev && webpack && node server.js",
    "ssr:cw": "ng build --aot=true --output-hashing=all --named-chunks=false --build-optimizer=true --watch",
    "ssr:sw": "ng run universal-demo:server:dev --watch",
    "ssr:webpack": "webpack --watch",
    "ssr:server": "nodemon server.js",
    "build": "ng build",
    "build:server": "ng run universal-demo:server:production",
    "build:prod": "ng build --prod",
    "build:universal": "ng build --prod && ng run universal-demo:server:production && webpack --progress --colors",
    "server": "node server.js",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "build:prerender": "npm run build:universal && npm run generate:prerender",
    "generate:prerender": "node prerender.js"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "6.0.6",
    "@angular/common": "6.0.6",
    "@angular/compiler": "6.0.6",
    "@angular/core": "6.0.6",
    "@angular/forms": "6.0.6",
    "@angular/http": "6.0.6",
    "@angular/platform-browser": "6.0.6",
    "@angular/platform-browser-dynamic": "6.0.6",
    "@angular/pwa": "0.6.8",
    "@angular/router": "6.0.6",
    "@angular/service-worker": "6.0.6",
    "@gorniv/ngx-transfer-http": "2.0.1",
    "@ngrx/effects": "^6.0.1",
    "@ngrx/router-store": "^6.0.1",
    "@ngrx/store": "^6.0.1",
    "@ngrx/store-devtools": "^6.0.1",
    "@nguniversal/common": "6.0.0",
    "@nguniversal/express-engine": "6.0.0",
    "@nguniversal/module-map-ngfactory-loader": "6.0.0",
    "@ngx-meta/core": "6.0.0-rc.1",
    "@ngx-translate/core": "10.0.2",
    "@ngx-translate/http-loader": "3.0.1",
    "angular2-masonry": "^0.4.0",
    "cookie-parser": "1.4.3",
    "core-js": "2.5.7",
    "imagesloaded": "^4.1.4",
    "moment": "^2.22.2",
    "morgan": "^1.9.0",
    "ng-lazyload-image": "^4.0.0",
    "ng-zorro-antd": "0.6.6",
    "ngx-cookie-service": "1.0.10",
    "ngx-countdown": "^3.0.1",
    "ngx-infinite-scroll": "^6.0.1",
    "ngx-masonry": "^1.1.0",
    "ngx-pagination": "^3.1.1",
    "ngx-pipes": "^2.2.0",
    "ngx-qrcode2": "0.0.9",
    "node-fetch": "2.1.2",
    "rxjs": "6.2.1",
    "rxjs-compat": "^6.2.1",
    "rxjs-tslint": "0.1.4",
    "videogular2": "^6.2.1",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "0.6.8",
    "@angular-devkit/schematics": "^0.6.8",
    "@angular/cli": "6.0.8",
    "@angular/compiler-cli": "6.0.6",
    "@angular/language-service": "6.0.6",
    "@angular/platform-server": "6.0.6",
    "@types/jasmine": "2.8.8",
    "@types/jasminewd2": "2.0.3",
    "@types/node": "10.3.4",
    "codelyzer": "4.3.0",
    "jasmine-core": "3.1.0",
    "jasmine-spec-reporter": "4.2.1",
    "karma": "2.0.3",
    "karma-chrome-launcher": "2.2.0",
    "karma-cli": "1.0.1",
    "karma-coverage-istanbul-reporter": "2.0.1",
    "karma-jasmine": "1.1.2",
    "karma-jasmine-html-reporter": "1.1.0",
    "localstorage-polyfill": "^1.0.1",
    "nodemon": "1.17.5",
    "preboot": "^6.0.0-beta.4",
    "protractor": "5.3.2",
    "ssri": "6.0.0",
    "tslint": "5.10.0",
    "typescript": "2.7.2",
    "webpack-cli": "3.0.8"
  }
}

commented

The problem is found because the token interceptor is set up in the project, and all HTTP requests are sent out after the interceptor processing, and the server does not seem to support the token related operations.

The problem is found because the token interceptor is set up in the project, and all HTTP requests are sent out after the interceptor processing, and the server does not seem to support the token related operations.

how to solve this problem? My post requests body are not be sending