Single Apache Virtualhost for Serving Angular Front End with a Dynamic API
October 11, 2025
Because Angular, on production, is basically a set of static files, and a dynamic API relies on Apache serving only one static file (e.g. index.php), and the two sets don't collide, we can serve them from the same virtualhost with a small bit of care. To do so, we use standard apache rewrite rules to redirect all requests that don't resolve to a real static file to the API's single static file (again, e.g. index.php). Otherwise we just serve the static file (angular ts or json, image, css, etc).
Where we need to be careful is in the deployment. I tend to lock in the API first and it stays, more or less, fixed during development of the front end. This is what I initially clone into my production source tree. Then I have a CI/CD pipeline that builds my front end, tests it, and if all is well, I use rsync to sync it to my document root in the source tree. The rsync command deletes old files with the exclusion of the 3 static files that my API provided:
rsync -e ssh -avz \
--delete \
--exclude index.php \
--exclude favicon.ico \
--exclude robots.txt \
dist/my_project/browser/ my-server.com:/var/www/my_project/public/
My virtualhost configuration uses standard rewrite rules as follows:
<Directory /var/www/my_project/public>
# The following rule tells Apache that if the requested filename
# exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
</Directory>
tags: angular, apache, back end, front end, laminas, laravel
Note: All comments are vetted before being published to the site. Html tags will be stripped. Markdown is enabled.
Angular + Laravel: CORS and Credentials in my Local Dev Environment
September 17, 2025
I've been working a lot lately with Angular 20 front ends and Laravel + Sanctum back end APIs. One big issue I came across was getting my session cookie sent to the back end when making requests using Angular's HttpClient. The issue didn't show up in production where I had Laravel's CORS config setup working. But on my local dev setup, I couldn't get authorization cookies in the requests. The responses all had a set-cookie header, the requests were properly prepared with the withCredentials: true
option (using an Angular interceptor). I ended up using an Authorization: bearer <token>
solution. It worked, but is more likely to be leaked.
Finally, I solved the issue. On the dev server, Angular uses ng serve, running by default on localhost:4200
. Laravel's php artisan serve uses 127.0.0.1:8000
. Cookies don't like that. They are domain aware and only want to stay on the domain they were issued from. Unlike CORS allowed origins, they don't care about protocol or port, but like CORS, cookies don't see localhost
as the same domain as 127.0.0.1
. So, that was the problem. Cookies can easily dismiss sub-domain differences (api.a.com works with www.a.com) so that's why production was okay - it's the same domain, just with a sub-domain difference.
The fix was simple. I set in my local dev's Laravel .env file to use
SESSION_DOMAIN=localhost
SECURE_COOKIE=false
Then I started Laravel with php artisan serve --host localhost
and started ng serve
(default is localhost). Finally all the credentials (err, session cookie) went back and forth.
tags: angular, laravel, security, software
Note: All comments are vetted before being published to the site. Html tags will be stripped. Markdown is enabled.
MySQL ODBC with Excel 2011 on OSX
January 24, 2011
I had a hard time getting the MySQL 5.1.8 ODBC driver to work with Excel 2011 on my work MacBook. I'm running OSX 10.6 (Snow Leopard), but this issue seems to go back some ways.
Apparently, the problem has to do with Microsoft Query being a native PPC 32 bit app, while Excel 2011 is an Intel native 32 bit app.
The solution was to use lipo to combine the distinct Mac Intel 32-bit ODBC driver with the PPC 32 bit driver.
To do this, download and extract the myodbc connector drivers from the MySQL site in tar.gz format. You need both the intel-x86-32bit and the ppc-32bit downloads. Extract them both next to each other in a tmp dir (/Users/drew/tmp, or whatever). Then, from your tmp dir, use lipo to make a multi-arch version. (To widen out the text area so you can see the full command, use my "hide panel" button to hide the right column of this page. Also, remember that backslash means "continue command on next line."):
$ lipo mysql-connector-odbc-5.1.8-osx10.5-powerpc-32bit/lib/libmyodbc5-5.1.8.so \
mysql-connector-odbc-5.1.8-osx10.6-x86-32bit/lib/libmyodbc5-5.1.8.so \
-output ./libmyodbc5-5.1.8.so \
-create
This will create a new libmyodbc5-5.1.8.so in the current directory with both architectures supported. You can test this by running:
$ lipo ./libmyodbc5-5.1.8.so -info
You can then sudo copy this to /usr/local/lib on top of any other libmyodbc5-*.so.
Also, be sure that /usr/local/lib/libmyodbc5.so a symlink to the new file. I had an actual file there rather than a symlink and it caused some additional pain.
tags: excel, mac, mysql, odbc, office 2011, osx
Note: All comments are vetted before being published to the site. Html tags will be stripped. Markdown is enabled.