SSR- Spartacus : Browser language detection not working because accept-language header is empty - server-side-rendering

We implement the browser language detection en SSR based on accept-language header retrieved from the Request Object.
the logic works fine on Staging environnement + locally with SSR, but on production after adding some logs , the header (accept-language) is empty in SSR.
**Implementation : **
private getBrowserLanguage(): string | null {
let language;
if (isPlatformBrowser(this.platformId)) {
language = this.winRef.nativeWindow?.navigator.language;
}
if (isPlatformServer(this.platformId)) {
language = this.request.headers['accept-language'] || '';
}
if (language) {
language = language.slice(0, 2);
return language;
}
return null;
}
Is there any reason why this header is missing only on production ?
Is there another approch to get the browser language on SSR ?

Related

Sending "Server Params" through Postman :

Thanks to Symfony HttpFoundation component , we can retrieve the server params like the following script :
// retrieves SERVER variables
$request->server->get('HTTP_HOST')
So, i have the following construct and i'd like to have the server parameters :
public function __construct(RequestStack $requestStack)
{
$request = $requestStack->getCurrentRequest();
$this->country = self::DEFAULT_COUNTRY;
$this->lang = self::DEFAULT_LANG;
$this->brand = self::DEFAULT_BRAND;
$this->jobBrand = $this->brand;
if ($request) {
if (!empty($request->server->get(self::ENV_COUNTRY_CODE))) {
$this->country = $request->server->get(self::ENV_COUNTRY_CODE);
}
if (!empty($request->server->get(self::ENV_LANG_CODE))) {
$this->lang = $request->server->get(self::ENV_LANG_CODE);
}
if (!empty($request->server->get(self::ENV_BRAND))) {
$this->jobBrand = $request->server->get(self::ENV_BRAND);
$this->brand = str_replace('pro', '', $this->jobBrand);
}
if (empty($this->country) || empty($this->lang)) {
throw new NoApacheLocaleException();
}
}
}
For information, during the testing phase, I used Postman as an http client.
So my question is: how can I send my parameters via Postman in order to get it through $request->server->get('param') ?
According to #Cerad and I'm convinced by his answer :
$_SERVER is initialized by PHP based on server side information. Does not use anything from the HTTP request. I suppose you could fake it for testing by using variable names like _server_http_host and adjust your code accordingly. But if you are using the Symfony framework then you might be better off using Symfony's functional testing approach.

Determing the physical path of a user friendly url

I have been asked to look at updating an old ASP.net Web Forms application to ASP.net 4.5; specifically to implement Microsoft's 'User Friendly' routing mechanism (NuGet Package Microsoft.AspNet.FriendlyUrls).
Generally, the upgrade was straightforward, but I am left with one problem.
The original developer attached/associated 'meta data' XML files to many of the web pages.. For example, /Products/Tables/Oak.aspx might also have the following meta file /Products/Tables/Oak.aspx.meta
When the page loads, it 'looks' for the meta file and loads it. In a non-rewritten URL environment, this was easy...
string metaUrl = Page.Request.Url.AbsolutePath + ".meta";
string metaPath = Page.Server.MapPath(metaUrl);
If (System.IO.File.Exists(metaPath)) {
LoadMetaFile(metaPath);
}
In a 'Friendly URL' environment, this is not so easy as the original URL might be rewritten to /Products/Tables/Oak or maybe even rewritten completely via a custom MapPageRoute() definition.
Does anyone know if there a way that I can find/determine the 'true' path of the page?
The solution posted by Petriq ASP.NET WebForms: Request.GetFriendlyUrlFileVirtualPath() returns empty string works perfectly in my scenario.
For reference, here is Petriq's code for his HttpRequest extension method:
using System.Web;
using System.Web.Routing;
using Microsoft.AspNet.FriendlyUrls;
namespace Utils.Extensions
{
public static class HttpRequestExtensions
{
public static string GetFileVirtualPathFromFriendlyUrl(this HttpRequest request)
{
string ret = string.Empty;
ret = request.GetFriendlyUrlFileVirtualPath();
if (ret == string.Empty)
{
foreach (RouteBase r in RouteTable.Routes)
{
if (r.GetType() == typeof(Route))
{
Route route = (Route)r;
// Following line modified for case-insensitive comparison
if (String.Compare("/" + route.Url, request.Path, true) == 0)
{
if (route.RouteHandler.GetType() == typeof(PageRouteHandler))
{
PageRouteHandler handler = (PageRouteHandler)route.RouteHandler;
ret = handler.VirtualPath;
}
break;
}
}
}
}
return ret;
}
}
}

#Url.Content doesnt resolve absolute path on one server but does on another

We currently have two different servers on same domain. But one server resolves
#Url.Content("~/api/User")'
as
http://domain.com/virtualdirectory/api/User
where as other server doesnt resolve it absolutely; rather it resolves it relatively like
api/user
The code base is same and we are using MVC4. I am not sure as to where we went wrong or if there is any IIS/DNS settings that need to be done in order to get this fixed.
All help is appreciated; thanks :)
This is related with the IIS Rewriting module in your IIS web server that return the path to http://domain.com/virtualdirectory/api/User
Take a look on the part of source code of #Url.Content below:
private static string GenerateClientUrlInternal(HttpContextBase httpContext, string contentPath)
{
if (String.IsNullOrEmpty(contentPath))
{
return contentPath;
}
// can't call VirtualPathUtility.IsAppRelative since it throws on some inputs
bool isAppRelative = contentPath[0] == '~';
if (isAppRelative)
{
string absoluteContentPath = VirtualPathUtility.ToAbsolute(contentPath, httpContext.Request.ApplicationPath);
return GenerateClientUrlInternal(httpContext, absoluteContentPath);
}
// we only want to manipulate the path if URL rewriting is active for this request, else we risk breaking the generated URL
bool wasRequestRewritten = _urlRewriterHelper.WasRequestRewritten(httpContext);
if (!wasRequestRewritten)
{
return contentPath;
}
// Since the rawUrl represents what the user sees in his browser, it is what we want to use as the base
// of our absolute paths. For example, consider mysite.example.com/foo, which is internally
// rewritten to content.example.com/mysite/foo. When we want to generate a link to ~/bar, we want to
// base it from / instead of /foo, otherwise the user ends up seeing mysite.example.com/foo/bar,
// which is incorrect.
string relativeUrlToDestination = MakeRelative(httpContext.Request.Path, contentPath);
string absoluteUrlToDestination = MakeAbsolute(httpContext.Request.RawUrl, relativeUrlToDestination);
return absoluteUrlToDestination;
}
Use the codes below to check whether your web servers are having the URL rewritten:
bool requestWasRewritten = (httpWorkerRequest != null && httpWorkerRequest.GetServerVariable("IIS_WasUrlRewritten") != null);
And Also:
private volatile bool _urlRewriterIsTurnedOnCalculated = false;
private bool _urlRewriterIsTurnedOnValue;
private object _lockObject = new object();
private bool IsUrlRewriterTurnedOn(HttpContextBase httpContext)
{
// Need to do double-check locking because a single instance of this class is shared in the entire app domain (see PathHelpers)
if (!_urlRewriterIsTurnedOnCalculated)
{
lock (_lockObject)
{
if (!_urlRewriterIsTurnedOnCalculated)
{
HttpWorkerRequest httpWorkerRequest = (HttpWorkerRequest)httpContext.GetService(typeof(HttpWorkerRequest));
//bool urlRewriterIsEnabled = (httpWorkerRequest != null && httpWorkerRequest.GetServerVariable(UrlRewriterEnabledServerVar) != null);
bool urlRewriterIsEnabled = (httpWorkerRequest != null && httpWorkerRequest.GetServerVariable("IIS_UrlRewriteModule") != null);
_urlRewriterIsTurnedOnValue = urlRewriterIsEnabled;
_urlRewriterIsTurnedOnCalculated = true;
}
}
}
return _urlRewriterIsTurnedOnValue;
}
In summary, If both requestWasRewritten and IsUrlRewriterTurnedOn
return true, that means one of your web server has IIS Rewrite Module
turned on and running while the other one doesn't have.
For more details on ASP.NET MVC source codes, please refer to this link:
http://aspnetwebstack.codeplex.com/
Hope it helps!

Changing the Endpoint.Binding of a WCF System.ServiceModel.ClientBase doesn't work

I'm working with a programmatically configurated WCF Client (System.ServiceModel.ClientBase). This WCF Client is configured using a CustomBinding, which has a TextMessageEncodingBindingElement by default.
Now when I try to switch to Mtom encoding, I change the Client's Endpoint.Binding property, which works fine. The Endpoint.Binding property show's it has changed.
Unfortunately when I execute one of the methods the WCF service exposes, it still uses TextMessageEncoding and I can't figure out why.
I've got it working though, by constructing a new ClientBase and passing the new EndPointBinding in the constructor:
socialProxy = new SocialProxyClient(SocialProxyClientSettings.SocialProxyMTomEndPointBinding, new EndpointAddress(SocialProxyClientSettings.SocialProxyEndPointAddress));
But when I try this it doesn't work:
socialProxy.Endpoint.Binding = SocialProxyClientSettings.SocialProxyMTomEndPointBinding;
These are my definitions for the EndPointBindings:
public static TextMessageEncodingBindingElement TextMessageEncodingBindingElement
{
get
{
if (_textMessageEncodingBindingElement == null)
{
_textMessageEncodingBindingElement = new TextMessageEncodingBindingElement() { MessageVersion = MessageVersion.Soap11 };
_textMessageEncodingBindingElement.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxDepth = 32,
MaxStringContentLength = 5242880,
MaxArrayLength = 204800000,
MaxBytesPerRead = 5242880,
MaxNameTableCharCount = 5242880
};
}
return _textMessageEncodingBindingElement;
}
}
public static MtomMessageEncodingBindingElement MtomMessageEncodingBindingElement
{
get
{
if (_mtomMessageEncodingBindingElement == null)
{
_mtomMessageEncodingBindingElement = new MtomMessageEncodingBindingElement();
_mtomMessageEncodingBindingElement.MaxReadPoolSize = TextMessageEncodingBindingElement.MaxReadPoolSize;
_mtomMessageEncodingBindingElement.MaxWritePoolSize = TextMessageEncodingBindingElement.MaxWritePoolSize;
_mtomMessageEncodingBindingElement.MessageVersion = TextMessageEncodingBindingElement.MessageVersion;
_mtomMessageEncodingBindingElement.ReaderQuotas.MaxDepth = TextMessageEncodingBindingElement.ReaderQuotas.MaxDepth;
_mtomMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength = TextMessageEncodingBindingElement.ReaderQuotas.MaxStringContentLength;
_mtomMessageEncodingBindingElement.ReaderQuotas.MaxArrayLength = TextMessageEncodingBindingElement.ReaderQuotas.MaxArrayLength;
_mtomMessageEncodingBindingElement.ReaderQuotas.MaxBytesPerRead = TextMessageEncodingBindingElement.ReaderQuotas.MaxBytesPerRead;
_mtomMessageEncodingBindingElement.ReaderQuotas.MaxNameTableCharCount = TextMessageEncodingBindingElement.ReaderQuotas.MaxNameTableCharCount;
}
return _mtomMessageEncodingBindingElement;
}
}
Can someone explain why changing the Endpoint.Binding programmatically doesn't work?
I believe that during construction of the ClientBase, the original Binding is used to create some helper objects. Changing the binding later does not change those helper objects.
To make any adjustments after construction, you likely need a custom Binding Behavior that you can tweak the internals of the Binding as you need. Use that in the construction so all helper objects are prepared for your later changes. As usual, all you want is one simple behavior change, but you will need to also write the ancillary helper classes to support your one behavior change.
See the SO thread: ONVIF Authentication in .NET 4.0 with Visual Studio 2010
For a discussion of CustomBinding issues.
See the blog post: Supporting the WS-I Basic Profile Password Digest in a WCF Client Proxy
For an example of a custom Behavior that lets you change the Username Token on the fly.
Perhaps something similar can be done to let you control the local endpoint binding on the fly.
UPDATE: More reading here in StackOverflow, and pages it links to and I believe i have found the answer you are looking for.
For PasswordDigestBehavior:
see: ONVIF Authentication in .NET 4.0 with Visual Studios 2010
and: http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/
For local NIC binding:
see: Specify the outgoing IP address to use with WCF client
// ASSUMPTIONS:
// 1: DeviceClient is generated by svcutil from your WSDL.
// 1.1: DeviceClient is derived from
// System.ServiceModel.ClientBase<Your.Wsdl.Device>
// 2: serviceAddress is the Uri provided for your service.
//
private static DeviceClient CreateDeviceClient(IPAddress nicAddress,
Uri serviceAddress,
String username,
String password)
{
if (null == serviceAddress)
throw new ArgumentNullException("serviceAddress");
//////////////////////////////////////////////////////////////////////////////
// I didn't know how to put a variable set of credentials into a static
// app.config file.
// But I found this article that talks about how to set up the right kind
// of binding on the fly.
// I also found the implementation of PasswordDigestBehavior to get it all to work.
//
// from: https://stackoverflow.com/questions/5638247/onvif-authentication-in-net-4-0-with-visual-studios-2010
// see: http://benpowell.org/supporting-the-ws-i-basic-profile-password-digest-in-a-wcf-client-proxy/
//
EndpointAddress serviceEndpointAddress = new EndpointAddress(serviceAddress);
HttpTransportBindingElement httpBinding = new HttpTransportBindingElement();
if (!String.IsNullOrEmpty(username))
{
httpBinding.AuthenticationScheme = AuthenticationSchemes.Digest;
}
else
{
httpBinding.AuthenticationScheme = AuthenticationSchemes.Anonymous;
}
var messageElement = new TextMessageEncodingBindingElement();
messageElement.MessageVersion =
MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None);
CustomBinding bind = new CustomBinding(messageElement, httpBinding);
////////////////////////////////////////////////////////////////////////////////
// from: https://stackoverflow.com/questions/3249846/specify-the-outgoing-ip-address-to-use-with-wcf-client
// Adjust the serviceEndpointAddress to bind to the local NIC, if at all possible.
//
ServicePoint sPoint = ServicePointManager.FindServicePoint(serviceAddress);
sPoint.BindIPEndPointDelegate = delegate(
System.Net.ServicePoint servicePoint,
System.Net.IPEndPoint remoteEndPoint,
int retryCount)
{
// if we know our NIC local address, use it
//
if ((null != nicAddress)
&& (nicAddress.AddressFamily == remoteEndPoint.AddressFamily))
{
return new System.Net.IPEndPoint(nicAddress, 0);
}
else if (System.Net.Sockets.AddressFamily.InterNetworkV6 == remoteEndPoint.AddressFamily)
{
return new System.Net.IPEndPoint(System.Net.IPAddress.IPv6Any, 0);
}
else // if (System.Net.Sockets.AddressFamily.InterNetwork == remoteEndPoint.AddressFamily)
{
return new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0);
}
};
/////////////////////////////////////////////////////////////////////////////
DeviceClient client = new DeviceClient(bind, serviceEndpointAddress);
// Add our custom behavior
// - this requires the Microsoft WSE 3.0 SDK file: Microsoft.Web.Services3.dll
//
PasswordDigestBehavior behavior = new PasswordDigestBehavior(username, password);
client.Endpoint.Behaviors.Add(behavior);
return client;
}

Security Sandbox Violation for module accessing localhost rest service in dev environment

Our app has a main module with link button, and clicking each link button loads different modules in the main content area.
For only one module, we get a Security Sandbox Violation when we try to do a multipart post of image data.
I can't find anything significantly different about this module, other modules do multipart posts fine.
I have added thre SWF and various folders (such as containing folder, its parent, etc.) to flash player global settings, but no luck. We added a liberal cross domain file but still no luck.
BTW, we are using ModuleLoader, should we try ModuleManager?
Please help.
Security Sandbox Violation
Connection to
http://localhost:PORTNUMBERHIDDEN/services/rest/mycompany/222/assetservice/asset?action=saveasset&objecttype=serviceOffer&objectid=5960&User-Agent=flex3.0&randomNum=1328144876976
halted - not permitted from
file:///C:/Perforce/Main/Portal/main/bin-debug/serviceOffer-2.4.0.18-SNAPSHOT.swf
I got the answer from this web post:
Unexpected Flash Security Exception When Using URLLoader
Instead of setting the contentType like this:
request.contentType = "multipart/form-data;boundary=" + POSTUploadBuilder.boundary;
Set the contentType like this:
request.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data;
boundary=' + POSTUploadBuilder.boundary));
This is how I create the boundry in my POSTUploadBuilder class:
public class POSTUploadBuilder {
private static var _boundary:String = "";
private static var _mainBoundary:String = "";
public static function get boundary():String {
if(_boundary.length == 0) {
var i:uint = 0;
var len:uint = 0x20;
for(; i < len; ++i) {
_boundary += String.fromCharCode(uint(97 + Math.random() * 25));
}
}
return _boundary;
}

Resources