Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Universal Support #1

Closed
crebuh opened this issue Jul 26, 2017 · 26 comments
Closed

Universal Support #1

crebuh opened this issue Jul 26, 2017 · 26 comments

Comments

@crebuh
Copy link

crebuh commented Jul 26, 2017

Hy guys,

great module! Are you planning to implement a way to use the module also on the server side.

So that the cookies are read from the intial request captured by node?

@CunningFatalist
Copy link
Contributor

Hey there :)

We did not plan on doing that. However, if you have some experience with this and would like to submit a pull request, we’d be very happy to accept it.

If you need that functionality right now, check out the ngx-cookie package. It already has a backend service.

Cheers from Berlin

@crebuh
Copy link
Author

crebuh commented Jul 26, 2017

Ok what a pity. But I will have a look into it.

The question is have can I easily extend your cookieService. I see no way in doing something like:

MyBackendService extends CookieService

so that I can use the DI of Angular to provide MyBackendService on the server-side and CookieService on the client-side like e.g.

providers: [ { provide: CookieService, useClass: MyBackendService } ],
Where do you see that ngx-cookie is supporting the universal approach? The old module did, but it is not compatible with ng4.

Cheers from Austria

@paroe
Copy link

paroe commented Jul 26, 2017

Currently the service has a strong dependency on document.cookie. As I see it an universal cookie service would have to abstract from it and use getter/setter for the cookie-string and instead work with the request object on the backend. That would require some refactoring and just extending the service as it is would not be feasible

@CunningFatalist
Copy link
Contributor

We got the idea about the ngx-cookie package’s support from this file: ngx-cookie/src/cookie-backend.service.ts. We didn’t actually test it, though...

@mrusmanali
Copy link

export * from './cookie-service/cookie.service';
is throwing error on node (angular universal)
node_modules/ngx-cookie-service/index.js:1
(function (exports, require, module, __filename, __dirname) { export * from './cookie-service/cookie.service';

SyntaxError: Unexpected token export
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:152:10)
at Module._compile (module.js:624:28)
at Object.Module._extensions..js (module.js:671:10)
at Module.load (module.js:573:32)
at tryModuleLoad (module.js:513:12)
at Function.Module._load (module.js:505:3)
at Module.require (module.js:604:17)
at require (internal/module.js:11:18)
at Object. (/Users/usmanali/projects/sivvi-server/dist/server.js:1:120927)
TypeError: Cannot read property 'create' of undefined
at /Users/usmanali/projects/sivvi-server/node_modules/@angular/core/bundles/core.umd.js:5531:78
at ZoneDelegate.invoke (/Users/usmanali/projects/sivvi-server/node_modules/zone.js/dist/zone-node.js:388:26)
at Object.onInvoke (/Users/usmanali/projects/sivvi-server/node_modules/@angular/core/bundles/core.umd.js:4792:33)
at ZoneDelegate.invoke (/Users/usmanali/projects/sivvi-server/node_modules/zone.js/dist/zone-node.js:387:32)
at Zone.run (/Users/usmanali/projects/sivvi-server/node_modules/zone.js/dist/zone-node.js:138:43)
at NgZone.run (/Users/usmanali/projects/sivvi-server/node_modules/@angular/core/bundles/core.umd.js:4609:69)
at PlatformRef.bootstrapModuleFactory (/Users/usmanali/projects/sivvi-server/node_modules/@angular/core/bundles/core.umd.js:5529:23)
at Object.renderModuleFactory (/Users/usmanali/projects/sivvi-server/node_modules/@angular/platform-server/bundles/platform-server.umd.js:1809:39)
at View.engine (/Users/usmanali/projects/sivvi-server/dist/server.js:1:1700)
at View.render (/Users/usmanali/projects/sivvi-server/node_modules/express/lib/view.js:135:8)

@CunningFatalist
Copy link
Contributor

Hello everyone,

we are currently working with Vue and not with Angular. This will not affect this package's support, of course. However, I have no experience with Universal and that will probably not change in the foreseeable future. I am going to mark this as help-wanted. If anyone would like to submit a pull request (with tests and an example environment), we would be very happy to accept it.

Cheers

Repository owner deleted a comment from tikemantns Aug 3, 2018
Repository owner deleted a comment from tikemantns Aug 3, 2018
@CunningFatalist
Copy link
Contributor

Just for the record. I deleted two comments that have absolutely nothing to do with this issue. The author also opened an issue with the exact same text, see #35

CunningFatalist pushed a commit that referenced this issue Nov 28, 2018
Improve platform identification and fix Angular Universal crashes. Addresses (but does not close) #1
@donbeave
Copy link

donbeave commented Apr 21, 2019

It looks like there is already existed solution for both (client and server side), for those who are using Angular Universal: https://www.npmjs.com/package/@ngx-utils/cookies

@MaxiDeBox
Copy link

MaxiDeBox commented May 28, 2019

Angular Universal
(function (exports, require, module, __filename, __dirname) { export * from './cookie-service/cookie.service';

SyntaxError: Unexpected token export
at new Script (vm.js:51:7)
at createScript (vm.js:136:10)
at Object.runInThisContext (vm.js:197:10)
at Module._compile (module.js:613:28)
at Object.Module._extensions..js (module.js:660:10)
at Module.load (module.js:561:32)
at tryModuleLoad (module.js:501:12)
at Function.Module._load (module.js:493:3)
at Module.require (module.js:593:17)
at require (internal/module.js:11:18)

@bastienlemaitre
Copy link

Hi, use this
https://gist.github.com/bastienlemaitre/52bdf8146e368bf1759b883e742316a2
Then include it into your app.server.module.ts

import { AppModule } from './app.module';
import { CookieService } from 'ngx-cookie-service';
import { CookieServerService } from './cookie-server.service';

@NgModule({
    imports: [
        AppModule,
        ServerModule,
        ServerTransferStateModule,
        ModuleMapLoaderModule,
        FlexLayoutServerModule
    ],
    providers: [
        {
            provide: CookieService,
            useClass: CookieServerService
        }
    ],
    bootstrap: [AppComponent]
})
export class AppServerModule { }

@msonowal
Copy link

@bastienlemaitre
Can you provide more detail about the implementation as this will still lead to document undefined errors

Repository owner deleted a comment from SimonCropp Mar 9, 2020
@stevermeister
Copy link
Owner

ok, so we need a solution for the Document object, right?

@DavidCMeier
Copy link

DavidCMeier commented Mar 16, 2020

We solved that creating a class and inyecting the RESPONSE and REQUEST, but we passes that in server.ts... so we can use this.request.headers.cookie and this.response.cookie. So this solution probably is not valid for all people.

in the server.ts where you render we passes that:

res.render('index', {
  req: req,
  res: res,
  providers: [
    {
      provide: REQUEST, useValue: (req),
    },
    {
      provide: RESPONSE, useValue: (res),
    },
  ],
})

now in the cookie.server.ts we injected:

  constructor(
    @Optional() @Inject(REQUEST) private request: Request,
    @Optional() @Inject(RESPONSE) private response: Response,
  ) {
  }

And now we can implement the methods.

this.request.headers.cookie
this.response.cookie

@stevermeister
Copy link
Owner

hm, maybe there is a more simple solution?

@DavidCMeier
Copy link

DavidCMeier commented Mar 19, 2020

I hope! haha our problem was that we need to use the cookie from the request and the response... Don't know other solution know...

That is our cookie-server.service.ts

import { Inject, Injectable, Optional } from '@angular/core'
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'
import { Request, Response } from 'express'


@Injectable({
  providedIn: 'root',
})
export class CookieServerService {

  constructor(
    @Optional() @Inject(REQUEST) private request: Request,
    @Optional() @Inject(RESPONSE) private response: Response,
  ) {
  }

  check(name: string): boolean {
    const cookies = this.getAll()
    return !!cookies[name]
  }

  delete(name: string, path?: string, domain?: string) {
    this.response.cookie(name, '', {expires: new Date('1999-01-01'), path: path})
  }

  get(name: string): string {
    const cookies = this.getAll()
    return cookies[name] || ''
  }
  getAll() {
    return typeof this.request.headers.cookie === 'string'
      ? decodeURIComponent(this.request.headers.cookie).split(';').reduce((cookies, cookie) => {
        const val = cookie.split('=')
        return {...cookies, [val[0].trim()]: val[1] }
      }, {})
      : {cookies: this.request.headers.cookie.map(decodeURIComponent)}
  }

  set(name: string, value: string, expires?: Date, path?: string, domain?: string, secure?: boolean, sameSite?: 'Lax' | 'None' | 'Strict') {
    this.response.cookie(name, value, {expires, path, domain, secure, sameSite})
  }

}

I hope that can help you! If you need something more tell me :)

Edit: Important Thing! this.response.cookie is encodeUri by default! hahaha i had problem with this xD

@stevermeister
Copy link
Owner

What I got from here - https://angular.io/guide/universal
That I only need to replace window.document to DOCUMENT

@DavidCMeier
Copy link

Probably that is the solution, but i try to use DOCUMENT and i get this error ERROR Error: NotYetImplemented

Probably I don't used correctly hehe, i will try later to remplace my RESPONSE and REQUEST to DOCUMENT.

And one more thing... i think is better option create a server service than replace the original service with Document. If you replace in the original service you need to use isPlatformBroswser (or server) in every place.

Thanks for your Work @stevermeister ! :)

@UltraKenchie
Copy link

Used @DavidCMeier 's solution! Men that was clean! Almost lost hope since universal said there won't be any plans for cookie on server side. Only had to modify some functions and it was good to go! :)

@stevermeister
Copy link
Owner

I just realized that I'm not sure what is expected behavior for cookie service on server side.

@pavankjadda
Copy link
Collaborator

@stevermeister I think we should implement this. I do see many projects using SSR. I might be able to implement this.

@stevermeister
Copy link
Owner

@pavankjadda we can think about own way, but are there any standard for server-side cookies?

@pavankjadda
Copy link
Collaborator

@stevermeister honestly I have no idea about standard. But I can tell you this. In one of my recent NextJS (React) projects, I used modified version of my library react-cookie-service. With simple changes I was able to get it working. I can try to do that same here, test it with sample projects. Perhaps we can people in this thread to test it.

@stevermeister
Copy link
Owner

but I conceptually don't understand it.
we have cookies only on the client side.
how do you want to get them on the server?
obviously, we can return an async object and wait till we have data on the client, but it will be not very consistent

@pavankjadda
Copy link
Collaborator

but I conceptually don't understand it.

we have cookies only on the client side.

how do you want to get them on the server?

obviously, we can return an async object and wait till we have data on the client, but it will be not very consistent

You don't have to. We still store them in browser but you just have to make sure document is available before accessing it. Would you mind enabling GitHub discussions for this project? We can discuss it over there.

@pavankjadda
Copy link
Collaborator

pavankjadda commented Oct 9, 2021

@stevermeister I created sample repo that demonstrates this. Clone the project and run as per instructions in Readme.md file

@deba10106
Copy link

@pavankjadda I used your code and got "Cannot read property 'getHeader' of null"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests