-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.json
More file actions
73 lines (73 loc) · 47.7 KB
/
index.json
File metadata and controls
73 lines (73 loc) · 47.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
[{
"title": "Iterators & Generators in Python",
"date": "",
"description": "A detailed description about iterators and generators, and the differences between them.",
"body": "This post aims to describe the basic mechanisms behind iterators and generators.\nIterator protocol As in many programming languages, Python allows to iterate over a collection. The iteration mechanism is often useful when we need to scan a sequence, operation that is very common in programming. In Python the iterator protocol involves two components: an iterable and an iterator.\nIterable The iterable is the container through which we want to iterate. It is the object that needs to be scanned to retrieve all the elements (or some of them). Some of well-known iterables are lists, tuples, dictionaries, ranges. In the iterator protocol the iterable exposes a iter method that returns an iterator object.\nIterator The iterator is the data structure that allows the scan through the container. It could seem a complication, but actually, with the separation of concerns, it lets the developer separate the concept of container, from the concept of iteration. The container object doesn\u0026rsquo;t need to keep the state of an iteration and furthermore, on the same object, many iterations at the same time can take place, so keeping the iteration state in a different object is a must. The container is a collection of elements, while the iterator is kind of an handler of the container, it exposes the same elements (owned by the container) one-by-one with a specific order and . In the iterator protocol, the iterator exposes two methods: iter and next. While the first one return the object itself (it allows the usage of both container and iterator in for and in statements), the latter return the next item from the container. What does it make the iterator end the iteration? The StopIteration exception.\nIterable and Iterator Examples Below an example of iterator protocol implementation:\n And its usage:\n Generator Generators are methods with yield statements. The yield statement has the power to suspend the function execution and store its state, so that it can be resumed. Behind the scenes, python returns the control to the function caller and save the function state; in this way, at the next execution, the function will start where it left, without letting the developer worrying about the state of the function. Generators ARE iterators, but not vice-versa.\nHere an example of generator:\n and its usage:\n Async generator Like generators they are async function with a yield statement.\nConclusions Iterators are iterables. Iterators are objects that implement the iterator protocol consisting in implementing both __iter__ and __next__. Iterator iterations stop when StopIteration is raised. Generators are methods with yield statements. Async generators are async methods with yield statements. Whenever possible, generator must be the preferred method due to its simplicity, while the protocol implementation gives much more control. Resources Iterator types Generator types Yield expression Generators and iterators ",
"ref": "/blog/python-iterators-generators/"
},{
"title": "Angular Dynamic Content",
"date": "",
"description": "An exploration of the different ways to dynamically change the content of a component.",
"body": "In many cases we would change the content of a component dynamically, like for instance, to allow the user to change view or to let the children render the data retrieved and elaborated from its parent component. Here below we are going to show some techniques to create a component without deciding how the data would be shown. According with the application needs, each technique has its own strengths, but all of them encourage component reusability. We are going to describe:\n Content projection Dynamic templates Dynamic component creation All the code is available on github and Stackblits.\nProjection This is the simplest technique, and it allows the component user to decide what to show within the component. This could be useful, for example, if we want a container component to decide the main content structure without forcing what will be render in a certain section.\nFirst of all, we need to use the ng-content tag in the dynamic component. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \nThen, when we use the component, we could include all the content we want within the new component tag. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \nA more flexible way to use content projection can be achieved by using the class selector. In this case, the dynamic content specifies by using a class selector where the content will be injected.\n .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } Now, in the component user, we could include two elements that will be injected in the component. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \nDynamic Template Dynamic template is a very easy to use, but it comes with some problems in terms of flexibility, so it could be a good choice in case of simple mechanisms to be implemented. A typical example could be the rendering of two elements according with a condition.\n .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } It could be very useful also to avoid template part repetitions, by writing the html part once, and by using the template context to pass data to the template. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \nDynamic Component creation The dynamic component creation is by far the most flexible technique to use, because it allows to choose the instant on which the component will be created. On the counterpart, it is the most complicated to write, even if, after the first times, everything becomes more clear and easy to repeat.\nTo implement this technique we need:\n a container tag directive, used to reference the container from within the parent component, to tag where the new child component will be rendered. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \n from the parent component, we need to reference the container using the @ViewChild annotation. .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \n in the parent component, we use the ComponentFactoryResolver to create an instance of the component to be created .emgithub-container table tbody tr td:not(:first-child) { text-align: left; } \n Conclusions As many other times in programming, there are different ways to accomplish the same task, but often it depends on what are the software requirements and what is the result we want to achieve. This article isn\u0026rsquo;t intended to be a detailed guide about these techniques, but only a general description about some of the possibilities offered by Angular to dynamically draw content within a component.\nResources ng-content ng-template, ng-container and ng-template-outlet Dynamic Components ",
"ref": "/blog/angular-dynamic-content/"
},{
"title": "CSP and CORS",
"date": "",
"description": "Definitions and relation between Content-Security-Policy and Cross-Origin-Resource-Sharing",
"body": "What is CSP CSP stands for Content Security Policy and it is a security mechanism that helps to protect or mitigate some common attacks such as XSS (Cross-site scripting). It can be set by means of Content-Security-Policy HTTP header or using HTML meta tag.\nHTTP header:\nContent-Security-Policy: policy HTML Meta tag:\n\u0026lt;meta http-equiv=\u0026#34;Content-Security-Policy\u0026#34; content=\u0026#34;policy\u0026#34;\u0026gt; A policy describes a set of directives composed by the area in which the rule is applied and the rule itself. The policy directive default-src 'self' says to load all the content from the site\u0026rsquo;s origin, while if we want to load the content from the site and from another trusted domain, the policy would be Content-Security-Policy: default-src 'self' *.trusted.com.\nWhat is CORS CORS stands for Cross-Origin Resource Sharing and it is a mechanism that permits a web application running at an origin to access resources served from a different origin. What is an origin? The origin is identified by domain, protocol and port. It uses a set of HTTP headers to declare what are the domains entitled to access the resource. Let\u0026rsquo;s have a look at the following scenario:\n We have a web application running on domain-a.com We have a web service running on domain-b.com domain-a.com web app wants to access the service published on domain-b.com The service on domain-b.com should enable CORS by properly setting HTTP Headers. The headers involved in CORS are:\n Access-Control-Allow-Origin - Origin can load the resource Access-Control-Allow-Methods - Methods can be used to access the resource Access-Control-Allow-Headers - Request headers allowed Access-Control-Max-Age - Value in seconds describing for how long the pre-flight response is cached (wait, pre-what?) Pre-flight request When the browser encounters a cross-domain request, it performs a so-called pre-flight request. In practice it performs an HTTP request using the OPTIONS method to verify if CORS is enabled. If and only if the response is successful (response code 204 - No Content) and the previously mentioned HTTP headers are properly sets, the browser will send the real request.\nRelation So, what is the relation between CSP and CORS?\nLet\u0026rsquo;s have a look at the previous scenario again.\n We have a web application running on domain-a.com We have a web service running on domain-b.com domain-a.com web app wants to access the service published on domain-b.com As we have previously said, web service exposed on domain-b.com must enable CORS, but that could be not enough. If we configured CSP on domain-a.com web application, we need also to relax the connect-src policy directive allowing https://domain-b.com. So to properly run the previous scenario:\n Enable CSP on domain-a.com Enable CORS on domain-b.com, by allowing domain-a.com using the Access-Control-Allow-Origin header. Relax the CSP (header or HTML tag), by setting the connect-src policy directive to allow the domain-b.com connection. Very important notes Please, setting CSP to be able to connect to everything (*) is a BAD CSP configuration, unless you know what you are doing. Please, setting CORS to return always the Access-Control-Allow-Origin header set with * is a BAD CORS configuration, unless you know what you are doing. Resources W3c CSP2 specification CSP HTTP Header W3c CORS specification MDN CSP MDN CORS ",
"ref": "/blog/csp-and-cors/"
},{
"title": "Angular and Rxjs Http Requests: Common scenarios",
"date": "",
"description": "How to perform http requests using rxjs; single, parallel and mixed",
"body": "Any modern web application needs soon or later to perform some http request to retrieve data. Here below I\u0026rsquo;ll describe some common scenario and how to perform such requests using RxJS.\nSingle request The most common scenario, no special rxjs handling, since that Angular provides an Http service that returns an Observable.\nservices.getItems().subscribe(); Is that easy? Yes. In the particular example, I assumed the http service call was inside the service.getItems method, but it could be a fetch or anything else returning an observable.\nParallel requests In this scenario instead, we want to perform multiple parallel requests. A common example could be:\n We perform an http request that returns a list of items For each item, we need to perform another request to fill some item detail No, if you are thinking to apply word-by-word the solution described by point 2, it is not the correct one, even if it can seem logically feasible.\n!!Bad code!! responses = [] items.forEach((item, index) =\u0026gt; { service.get(item.id).subscribe( (response) =\u0026gt; { responses[index] = response; }); });\nWhy not? Because we cannot control the requests, we can\u0026rsquo;t know when all of them will be resolved and what is their state.\nOur goal can be achieved by using the forkJoin operator. It is often compared to Promises.all(), but many of you could have never used it, so let\u0026rsquo;s do an example.\nOur friend is following a run on tv, but we are not fans, so we are not interested in the run winner; the only thing we want to know is when the run is finished, nothing else (we don\u0026rsquo;t watch tv, we want to have a beer). With forkJoin we wait for all the runners to finish. Practically it receives an array of observables and then we can subscribe to an array of results having the same array index of the requests.\nHere is the resulting code:\nitemRequests = items.map((item) =\u0026gt; service.get(item.id)); forkJoin(itemRequests).subscribe((results) =\u0026gt; { // do something with results }) But \u0026hellip;\nIt leads to a common error. What if a runner is disqualified? The run will still be valid for the remaining runners, right? Well, by default forkJoin is successful only if all the runners successfully finish their run, and this isn\u0026rsquo;t what we usually want.\nHere is the forkJoin code snippet that successfully finish even if one of the requests fails:\nitemRequests = items.map((item) =\u0026gt; { return service.get(item.id).pipe( // not the best way to handle the error, // maybe we could retry, or set some placeholder instead catchError((err) =\u0026gt; of(undefined)); ) }); forkJoin(itemRequests).subscribe((results) =\u0026gt; { // do something with results }) In that way, we have the results filled differently according with the responses status, and if some request fails, we have undefined in the corresponding item among the results. So if the request[1] fails, results[1] will be undefined.\nSequential requests For sequential requests there are many operators that can be used to achieve almost the same result, but they have slightly different behaviours.\n concatMap mergeMap switchMap Assuming we want two perform 2 requests:\n mergeMap: the second request starts as soon as possible, without waiting the end of the first one, so the order of the subscription isn\u0026rsquo;t guaranteed (if important, it must be manually handled in some way) concatMap: the second request starts only after the end of the first one and the emitted results will maintain the order of the subscriptions. So the first result corresponds to the first subscription and so on. switchMap: it is slightly different, because it executes the inner subscription only after the first one, but in particular, only one requests at a time will be active. One big advantage of using this operator is that on each emission, it can cancel existing requests. Single request followed by parallel requests After analysing both single and multiple requests, we can compose them.\n!!Bad code, don\u0026rsquo;t use it // get the items service.getItems().subscribe((items) =\u0026gt; { itemRequests = items.map((item) =\u0026gt; { return service.get(item.id).pipe( // not the best way to handle the error, // maybe we could retry, or set some placeholder instead catchError((err) =\u0026gt; of(undefined)); ); }); forkJoin(itemRequests).subscribe((results) =\u0026gt; { // do something with results }) });\nAs you maybe already know, performing a subscription within a subscribe is a very bad practice and it MUST BE absolutely avoided. This looks very similar to the callback hell problem, nowadays almost forgotten fortunately.\nWhat is the right way to compose them? By using our wonderful switchMap operator.\n// get the items service.getItems().pipe( switchMap((items) =\u0026gt; { // it must return an observable itemRequests = items.map((item) =\u0026gt; service.get(item.id).pipe( // not the best way to handle the error, // maybe we could retry, or set some placeholder instead catchError((err) =\u0026gt; of(undefined)); )); return forkJoin(itemRequests); }), tap((itemRequestsResponses) =\u0026gt; { // here we have the array of responses returned from forkJoin }) ); If we would compose the response by using both the first response and the responses coming from the forkJoin: // get the items service.getItems().pipe( switchMap((items) =\u0026gt; { // it must return an observable itemRequests = items.map((item) =\u0026gt; service.get(item.id).pipe( // not the best way to handle the error, // maybe we could retry, or set some placeholder instead catchError((err) =\u0026gt; of(undefined)); )); return forkJoin(itemRequests).pipe( map((itemRequests) =\u0026gt; { // compose the response in some way using both itemRequests and items }) ); }), tap((ourComposedResponse) =\u0026gt; { // here we have the object composed in the inner map of the forkJoin }) );\nConclusions Take Away forkJoin performs parallel requests, but each fail should be handled singularly If we have one request that uses a response of another request it\u0026rsquo;s likely that we need switchMap NO Subscribe-in-Subscribe Resources RxJS LearnRxJS Angular HTTP guide ",
"ref": "/blog/angular-rxjs-http-requests/"
},{
"title": "Git: Move Files Retaining History",
"date": "",
"description": "How to move files among git repository retaining the history",
"body": "Sometimes ago we need to create a new product, that shares many functionalities with the existing one. The first idea was to extract some of the code in a library, to be then imported and used independently in the two projects.\nAfter creating the repository for the library, the first action I would have done was copying the files from one repo to another. Well, it works like a charm, it’s fast and it doesn’t require any particular expertise, a normal drag and drop operation. What’s best? It could be a very effective approach, but \u0026hellip;\nDuring a PR review, I learnt there was a cleaver way to perform such operation and I wasn’t even aware of such possibility before:\n Moving files from one git repository to another retaining the history.\n Moving a single directory From the source repository:\ngit clone \u0026lt;src_repository\u0026gt; \u0026lt;src_repository\u0026gt;_clone # clone the src repository in new folder cd \u0026lt;src_repository\u0026gt;_clone git remote rm origin # remove the origin to avoid disasters in case of error git filter-branch --subdirectory-filter \u0026lt;directory\u0026gt; -- --all # the magic, rewrite the git history mkdir \u0026lt;directory\u0026gt; mv * \u0026lt;directory\u0026gt; # create the directory and move everything inside In the destination repository:\ngit remote add \u0026lt;src_repository\u0026gt; \u0026lt;git repository A directory\u0026gt; # clone clone the repository, if not previously done git pull repo-A master --allow-unrelated-histories # Import the src repository code into the dst repository git mv \u0026lt;directory_1\u0026gt; \u0026lt;desired_position\u0026gt; # Optionally, move the just imported files, into the desired position in the new repository Moving code file-by-file The operations required to move many files at once are conceptually the same. The extraction of the files to be moved will be performed by means of the following script (from Tom Hacohen blog article):\n After changing the script to include the files to be imported, it must be executed just before the git filter-branch ... command; this will create a single folder into the repository. So, to recap:\nDownload the script, and change it according with the files to be copied.\nFrom the source repository:\ngit clone \u0026lt;src_repository\u0026gt; \u0026lt;src_repository\u0026gt;_clone # clone the src repository in new folder cd \u0026lt;src_repository\u0026gt;_clone git remote rm origin # remove the origin to avoid disasters in case of error Execute the script previously modified here, so assuming the script has been saved in the parent folder:\n bash $(pwd)/../git-move.sh At this point, the repository contains only the folder and the files specified in the script.\ngit filter-branch --subdirectory-filter \u0026lt;directory\u0026gt; -- --all # the magic, rewrite the git history mkdir \u0026lt;directory\u0026gt; mv * \u0026lt;directory\u0026gt; # create the directory and move everything inside In the destination repository:\ngit remote add \u0026lt;src_repository\u0026gt; \u0026lt;git repository A directory\u0026gt; # clone clone the repository, if not previously done git pull repo-A master --allow-unrelated-histories # Import the src repository code into the dst repository git mv \u0026lt;directory_1\u0026gt; \u0026lt;desired_position\u0026gt; # Optionally, move the just imported files, into the desired position in the new repository Conclusions That easy? Yep. Despite the many commands to be run, the advantage of maintaining the history is priceless, especially when we need to investigate some issue, file history could be very useful.\n Tip: The process could seem counterintuitive, so I suggest to give it a try with some test repository. After the first time, everything will be much clearer.\n Resources A useful guide from @ayushya on Medium Tom Hacohen explains how to git move single files ",
"ref": "/blog/git-move-file-with-history/"
},{
"title": "Mongodb Query Profiler",
"date": "",
"description": "Steps involved to analyse the performance of a MongoDB query",
"body": "Some months ago, I was creating a web page to show some aggregated data, but I soon noticed the API used to retrieve the data was very slow. After investigating on the possible issue, we discovered the bottleneck: the database. The solution was to re-structure the data to make it consumable from a web page.\nAlthough I had used sometimes the SQLServer profiler, I had no experience about MongoDB profiler, so here below the steps involved to analyse a MongoDB query.\n It doesn\u0026rsquo;t apply to our case, but in many situations performance problems are related to missing or wrongly implemented MongoDB Indexes.\n Enable MongoDB profiler By default, MongoDB doesn\u0026rsquo;t profile any query. It is possible to set the profiling level executing:\ndb.setProfilingLevel(\u0026lt;profile_level\u0026gt;) where profile_level can be:\n 0 - the profiler is off, so it doesn\u0026rsquo;t collect any data. 1 - the profiler collects data only if the operation takes more than slowms (a configurable threshold). 2 - the profiler collects data for all operations. IMPORTANT: At the end of the analysis, please remember to disable profiling with: db.setProfilingLevel(0), since that it can affect MongoDB performance.\n Retrieve last query profile Once profiling is enabled, it is possible to retrieve last query profiled (meaning that the query must be executed after setting the profiling level) with the command:\ndb.system.profile.find().limit(1).sort({ts:-1}).pretty() Explain The explain command comes in handy, since that it provides information on many common operations such as aggregate, count, distinct, find, findAndModify, delete and update. Nevertheless a method with the same name, is available on collection and cursor also.\nSo if we want to analyse the information associated with an aggregate operation we can execute:\ndb.\u0026lt;collection_name\u0026gt;.explain(\u0026lt;verbosity\u0026gt;).aggregate(...) where:\n \u0026lt;collection_name\u0026gt; is the name of the collection on which the aggregation is performed \u0026lt;verbosity\u0026gt; is the level of verbosity we want to extract. Explain verbosity The explain command accepts one of the following verbosity levels:\n queryPlanner - It returns the queryPlanner information about the winning plan evaluation. executionStats - It returns queryPlanner and the executionStats information, but rejected plans are not included in the latter. allPlansExecution - It returns queryPlanner and the executionStats information about all the evaluated plans (including also rejected plans). Conclusion Only by understanding how the query was executed by MongoDB, we were able to improve its performance.\n Not our case, but I would remind that performance problems are often associated to missing or wrongly implemented indexes. If so, please have a look at MongoDB Indexes.\n Resources MongoDB database profiler Explain results MongoDB Indexes ",
"ref": "/blog/mongodb-query-profiler/"
},{
"title": "Security Headers on Static Websites",
"date": "",
"description": "Security implication on hosting a static website on GitHub Pages",
"body": "When I started this blog, I evaluated many options:\n blogging platform vs static-generated website self-hosted vs hosted solutions costs and many more. I ended up trying to build something very simple, consisting in a static website hosted on GitHub Pages. With this solution, I have been able to cut the cost on any host solution, since that, being a dev, I am quite comfortable in writing in a text editor. But soon some problem arises.\nI discovered the impossibility to harden the server to customize the response headers. Why should someone customize the response headers? The response to question is:\n \u0026ldquo;When she/he encounters securityheaders.com and she/he get an F\u0026rdquo;.\n I believe that many people do not apply the required security constraints due to the barriers they encounter to understand the reason behind. On the contrary, securityheaders.com made a very good job to let people understand what is wrong with the security headers, and why it is necessary to change them accordingly.\nWhy Although there is a misleading conception that static websites are intrinsically secure, web server misconfiguration represents one of the attack vectors shared among dynamic and static websites.\nWeb server misconfiguration can lead to well-known vulnerabilities such as:\n Referrer leakage\n With the Referrer-Policy, it is possible to instruct the browser not to send the referrer header along with requests. XSS (Cross-site scripting)\n Content-Security-Policy usage instructs the browser about the content will be rendered in a page Along with CSP security header, it would be useful to set the X-XSS-Protection header to instruct old browsers not to render the page if an attack is detected. Click-jacking\n The X-Frame-Options header can be used to instruct the browser if it is allowed rendering content in a frame. Tab nabbing\n Along with other mechanisms can be used to mitigate this attack, also setting the Referrer-Policy header can be useful. and many more.\n For a much detailed description about the risks associated with HTML5 page, please have a look at OWASP HTML5 Security Cheat Sheet.\nHow So, back to this blog, how it is possible to reach an A+ report, running a static website on GitHub Pages? No, you don\u0026rsquo;t need to pay something to improve your website security.\nA free plan on Cloudflare is enough 😎.\nWe are going to customize the response headers by using the Cloudflare Workers service provided by the Cloudflare free tier.\nHere below the script to be used. It can also be found on GitHub.\nlet securityHeaders = { \u0026#34;Content-Security-Policy\u0026#34; : \u0026#34;upgrade-insecure-requests\u0026#34;, \u0026#34;Strict-Transport-Security\u0026#34; : \u0026#34;max-age=2592000\u0026#34;, \u0026#34;X-Xss-Protection\u0026#34; : \u0026#34;1; mode=block\u0026#34;, \u0026#34;X-Frame-Options\u0026#34; : \u0026#34;DENY\u0026#34;, \u0026#34;X-Content-Type-Options\u0026#34; : \u0026#34;nosniff\u0026#34;, \u0026#34;Referrer-Policy\u0026#34; : \u0026#34;strict-origin-when-cross-origin\u0026#34;, \u0026#34;Feature-Policy\u0026#34;: \u0026#34;accelerometer \u0026#39;none\u0026#39;; camera \u0026#39;none\u0026#39;; geolocation \u0026#39;none\u0026#39;; gyroscope \u0026#39;none\u0026#39;; magnetometer \u0026#39;none\u0026#39;; microphone \u0026#39;none\u0026#39;; payment \u0026#39;none\u0026#39;; usb \u0026#39;none\u0026#39;\u0026#34; } let sanitiseHeaders = { \u0026#34;Server\u0026#34; : \u0026#34;My New Server Header!!!\u0026#34;, } let removeHeaders = [ \u0026#34;Public-Key-Pins\u0026#34;, \u0026#34;X-Powered-By\u0026#34;, \u0026#34;X-AspNet-Version\u0026#34;, ] addEventListener(\u0026#39;fetch\u0026#39;, event =\u0026gt; { event.respondWith(addHeaders(event.request)) }) async function addHeaders(req) { let response = await fetch(req) let newHdrs = new Headers(response.headers) if (newHdrs.has(\u0026#34;Content-Type\u0026#34;) \u0026amp;\u0026amp; !newHdrs.get(\u0026#34;Content-Type\u0026#34;).includes(\u0026#34;text/html\u0026#34;)) { return new Response(response.body , { status: response.status, statusText: response.statusText, headers: newHdrs }) } let setHeaders = Object.assign({}, securityHeaders, sanitiseHeaders) Object.keys(setHeaders).forEach(name =\u0026gt; { newHdrs.set(name, setHeaders[name]); }) removeHeaders.forEach(name =\u0026gt; { newHdrs.delete(name) }) return new Response(response.body , { status: response.status, statusText: response.statusText, headers: newHdrs }) } I took the script from the creator of securityheaders.com, from its post, where he exactly describes what each header is used for. I strongly recommend to have a look at rest of his blog for a detailed description of many security headers.\nResources Original Scott Helme post securityheaders.com GitHub Pages OWASP HTML5 Security Cheat Sheet HTTP Headers on MDN ",
"ref": "/blog/security-headers-on-static-websites/"
},{
"title": "SPA deployment with GitLab",
"date": "",
"description": "A small example of a single-page application deployment using GitLab, docker and nginx",
"body": "In the last projects, I started using GitLab, not only as git repository server, but also as DevOps platform. So here I am going to describe a very simple architecture to deploy a single page application using Docker and docker-compose, nginx. In this specific project I used also dotnet-core for the back-end API and VueJS as front-end framework, but it is language-agnostic, meaning that you can replace whatever back-end or front-end you prefer.\nFirst of all, following the separation of concerns, let\u0026rsquo;s consider each part on its own. I have created 3 repositories:\n Front-end Back-end Deploy I have considered using one single repo to maintain all the codebase, but I ended-up with this structure for the following reasons:\n Often the teams working on back-end and front-end are not the same, so in this way they are completely independent from each-other In that way the project structure can be re-used with all frameworks/languages combinations We are almost separating the local development phase, with the DevOps phase (apart from the inclusion of the gitlab-ci.yml files). Front-end static files generation I have used the VueJS and the related vue-cli tools to generate the static files, but it doesn\u0026rsquo;t really matter in the whole application; the only important thing is to generate static files.\nIn our case the gitlab-ci.yml file will look like:\nbuild site: image: node:latest stage: build script: - npm ci - npm run build artifacts: paths: - dist description =\n It creates a job named build site It executes the script in a docker image node:latest It creates a build stage to execute the following script in the image aforementioned: npm ci npm run build It stores the artifacts created in the dist directory. Back-end API build Since that we make use of dotnet-core, we need to build the project, so this step could be unnecessary if you choose some language that doesn\u0026rsquo;t require to be compiled (e.g. NodeJs, Python, etc\u0026hellip;).\nOur gitlab-ci.yml:\nbuild: image: microsoft/dotnet:sdk stage: build script: - dotnet restore - dotnet publish -c Release -o out artifacts: paths: - out As you can see, the file looks very similar to the previous one.\n It creates a build job It uses a different docker image to build the project microsoft/dotnet:sdk It creates a build stage to execute the following scripts: - dotnet restore # it restores the dependencies - dotnet publish -c Release -o out # it builds the project It stores the artifacts created in the out directory. So at the moment, we have 2 projects that produces their own artifacts. It\u0026rsquo;s time to let them talk!\n Deploy project Project structure |__ api | |__ Dockerfile |__ nginx | |__ nginx.conf |__ gitlab-ci.yml |__ docker-compose.yml This project performs the following steps:\n Retrieve files generated from the front-end Retrieve files generated from the back-end Set-up nginx docker-compose.yml:\nversion: \u0026#39;3\u0026#39; services: nginx: image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf - ./dist/:/var/www/html/ ports: - 80:80 - 443:443 networks: - proxy-net web: build: ./api/ networks: - proxy-net networks: proxy-net: From the docker-compose file it is important to notice two folders:\n ./dist/ used to map the static file folders the nginx container ./api/ the folder containing the Dockerfile used to setup the dotnet APIs container. For completeness here the content of the Dockerfile used to run the dotnet APIs.\n# Build runtime imageFROMmicrosoft/dotnet:aspnetcore-runtimeWORKDIR/appCOPY . .ENTRYPOINT [\u0026#34;dotnet\u0026#34;, \u0026#34;Api.dll\u0026#34;]Where Api is the name of the dotnet API project.\nnginx.conf:\nevents { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; server { server_name \u0026lt;name_of_the_server\u0026gt;; # TODO: to be replaced location / { # This would be the directory where your SPA static files are stored at root /var/www/html/; try_files $uri $uri/ /index.html; } location /api { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://web; proxy_ssl_session_reuse off; proxy_set_header Host $http_host; proxy_cache_bypass $http_upgrade; proxy_redirect off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection keep-alive; } } } The previous nginx configuration is to be intended as example only. For nginx production configuration please refer to the following resources\n Ssl-config generator by Mozilla Security Headers We are assuming this project is deployed by an agent running on a machine with docker-compose installed.\nLet\u0026rsquo;s have a look at gitlab-ci.yml.\ndeploy: stage: deploy only: - \u0026#34;master\u0026#34; environment: production script: - \u0026#34;curl -L --header \\\u0026#34;PRIVATE-TOKEN: $TOKEN\\\u0026#34; \\\u0026#34;https://gitlab.com/api/v4/projects/14072554/jobs/artifacts/master/download?job=build+site\\\u0026#34; --output artifacts.zip\u0026#34; - unzip artifacts.zip - \u0026#34;curl -L --header \\\u0026#34;PRIVATE-TOKEN: $TOKEN\\\u0026#34; \\\u0026#34;https://gitlab.com/api/v4/projects/10080203/jobs/artifacts/master/download?job=build\\\u0026#34; --output api.zip\u0026#34; - unzip api.zip - cp -R out/* api/ - sh down.sh - sh up.sh It creates a deploy job It creates a deploy stage with the following script section: - \u0026#34;curl -L --header \\\u0026#34;PRIVATE-TOKEN: $TOKEN\\\u0026#34; \\\u0026#34;https://gitlab.com/api/v4/projects/14072554/jobs/artifacts/master/download?job=build+site\\\u0026#34; --output artifacts.zip\u0026#34; - unzip artifacts.zip - \u0026#34;curl -L --header \\\u0026#34;PRIVATE-TOKEN: $TOKEN\\\u0026#34; \\\u0026#34;https://gitlab.com/api/v4/projects/10080203/jobs/artifacts/master/download?job=build\\\u0026#34; --output api.zip\u0026#34; - unzip api.zip - cp -R out/* api/ - docker-compose up --build -d So let\u0026rsquo;s dive deeper in the script commands:\n Retrieve the front-end artifacts by using the gitlab API (for non-enterprise users) It also requires to set the PRIVATE-TOKEN variable with a personal access token, that can be generated from User Settings -\u0026gt; Access Tokens Unzip the front-end artifacts Retrieve the back-end artifacts Unzip the back-end artifacts Run docker-compose Conclusion I have tried to describe only the steps necessary to deploy a single-page application using docker and GitLab, without considering the initial steps of repositories creation and GitLab runner setup.\nWhile the setup of the GitLab runner used to deploy the application is required, the front-end and back-end builds make use of the shared runners available in GitLab.\nFor further details, please don\u0026rsquo;t hesitate to get in touch!\n",
"ref": "/blog/gitlab-cd/"
},{
"title": "Browser Extension Development",
"date": "",
"description": "",
"body": "Web extensions or browser plugins can be used to improve browser functionalities. The following examples summarize the different goals they can have:\n no-script - to block script served from not-trusted domains ublock Origin - it is \u0026ldquo;a wide-spectrum blocker\u0026rdquo; dark-mode - it changes the appearance of web pages React Developer Tools - to inspect react-specific properties of a page that makes use of React. Anatomy of an extension The main components of a browser extension are:\n Manifest.json - it is the only mandatory file and it describes the extension itself. It is as an entry-point for the browser to declare what are the files/resources/permissions will be used.\n Background scripts - They contain the logic that are not strictly related to the single web-page. They are loaded when the extension is loaded and remain active until the extension is disabled or uninstalled.\n Content scripts - Unlike background scripts, they are loaded into web pages, so they can manipulates DOM exactly like normal script can do.\n UI components - They includes all the parts that permit a user to interact with the extension, by means of an HTML document. There are three different UI components:\n sidebar popup options page Web-accessible resources - They include all the resources that are made available to the scripts (e.g. HTML, images, jss, css)\n Extension pages - They are additional pages used to handle specific user interactions.\n Web-extension toolbox As for many browser APIs, also the web extension APIs can behave differently according with the browser on which they are executed. In case of cross-browser development it could be handful web-extension polyfill developed by Mozilla.\nFurthermore, to ease the development process, there is also web-extension toolbox and its related yeoman generator. Among the others it provides the following functionalities:\n Compiles the extension via webpack to dist/\u0026lt;vendor\u0026gt; Watches all extension files and re-compiles on demand Reloads extension or extension page as soon something changed After answering to some questions, it generates a ready-to-run web extension.\nDevelopment You only need to run npm run dev \u0026lt;vendor_name\u0026gt;, where \u0026lt;vendor_name\u0026gt; can be chrome, firefox, opera or edge; now you can load the generated extension in the browser of choice.\nBuild As easy as running npm run build \u0026lt;vendor_name\u0026gt;.\nConclusions So, what are you waiting for? Are you ready to develop your own browser plugin? I am already mine ;-)\nResources MDN Browser Extensions webextension-toolbox Mozilla web-ext ",
"ref": "/blog/browser-extension/"
},{
"title": "Let's Test",
"date": "",
"description": "A brief introduction about testing",
"body": "Preamble This article is not intended to cover the whole testing process due to its vastness. Having a glance at its Wikipedia page could give an idea of it. I am going to cover only the tip of the iceberg, but it is important to remind that bugs cannot be eliminated from the software, but in contrast, they must be discovered as soon as possible.\n The higher is the time passed since the bug come into the system, the higher is the cost to fix it.\n So any techniques that could be useful to identify a bug should be used, taking into account the resources available and the type of system to be implemented.\n+++\nI am going to focus to the developer point of view: what a developer can do (related to software testing) to improve the quality of the code? The first word that comes to mind is TDD. Of course, as already said, this isn\u0026rsquo;t the only way to implement software testing, and it is far from me saying that it is enough, but surely it is a good starting point. I strongly believe that TDD/BDD are very supportive techniques that could help writing more robust and stable software. The problem is mine: I haven\u0026rsquo;t ever applied it from scratch so far, so I decided to fill this defect from now on.\nAlthough I have been programming since about 5 years, I think to have very few practical experience about software testing. Please, don\u0026rsquo;t misjudge me about that. In past I wrote some test, but usually working in an already set up environment, by writing small tests regarding the functionality I was adding to the system. Here I am speaking about establishing a test-oriented development process.\nI won\u0026rsquo;t consider any language specific framework, but I am going to define only some of the main keywords.I am going to dive deep in details of some specific framework (hurrah, practice!) in some specific article, but not here.\nKeywords Unit test Unit test refers to a single unit of code. What actually is a unit? According with the paradigm used, a unit code can be a function or a class in case of object-oriented programming. The important thing is that, unit testing should not be performed by considering the success case only; on the contrary the unit test should take into account especially the corner case, in a defensive programming manner. Why? Because as a developer, you will try the normal workflow dozens, hundreds or maybe thousands of times.\nIntegration test On the other hand, integration tests should refer to the interaction of multiple units of code, by trying to locate interface issues. The integration tests can be seen in a hierarchical way: once a group of units are tested, it can be considered at the same time as a unit, a single module, to be integrated with other modules, so an integration test can be performed in an upper layer, and so on. Anyway the importance of the integration test should not be overlooked, since that with unit testing only, it is not possible to identify defects at the interface level.\nMock Mocking during test is fundamental. It is the process of creating an object that can simulate the behavior of a real object. It is necessary to simulate the behavior of a component because in the real world, often a unit is composed or depends on other units. To be sure to isolate the code to be tested, to avoid the side-effects can occur in other units, mock objects should be created, objects that simulate what the real object would do, but without the risk of defects that can occur externally with respect the unit to be tested.\nTDD Test-Driven Development is a software development process which involves the creation of the test before actually implementing the functionally. The process involves the following steps:\n Verify if the actually design fits good with the functionality to be added. If necessary, refactor the code to adhere to the new feature. Repeat the tests, to be sure that after refactoring everything still works properly. Write the tests for the new feature (at this point, all the new tests should fail). Implement the functionality to adhere to the specification represented by the tests (at the end of this step, all the tests should pass). If necessary refactor the code just implemented (cleanup if necessary, remove duplications, etc\u0026hellip;). Run the tests. The upside of the process is highlighted by the steps 1. and 4.: the step 1. permits to apply the refactoring of the existing code without being scared of it, and without leveraging the confidence; the step 4. is useful to maintain the code always clean to improve readability and maintainability; it could be useful also in some case, to try to figure out, if there is a solution with improves the performances, and such operation could be performed on step 4.\nBDD Behavior-Driven Development can be seen as a specialization of the aforementioned TDD, but it is oriented to the user. It involves the definition of the tests as a description of the desired behavior. It permits a clearer way of communication among different actors, when the process involves not only developers, but also QA Testers, which can define the specification of the tests in a domain-specific language, and then the developers can translate them (by means of automatic tools also), in a specific programming language.\n+++\nConclusion If I am not the only person in the world to have not yet established a real TDD strategy in the daily job, I strongly recommend giving it a try. Keep in mind, a very robust system, should be be tested as much as possible, from every perspective, both functional and not function, by taking into account also features too often overlooked like security and performance; so please consider investigating also on performance test and security test; I will try to describe them in a related post.\n",
"ref": "/blog/lets-test/"
},{
"title": "Getting Started With My Website :-)",
"date": "",
"description": "Main reasons behind the blog.",
"body": "Here in this post, I am going to explain why I am starting writing something on INTERNET and what I am going to share. I perfectly know that there are so many sites today, describing almost everything, but these are only some of the reasons which drive me at this point:\n to improve my language skills; to improve my online presence; to receive feedbacks (feedback is the key to grow up); to share what I do (and how, I am going to list also some of my biggest mistakes). And what\u0026rsquo;s about the content?\nWell regarding the content I am not completely sure about what I am going to describe, but approximately it could be:\n coding (small snipped of code, that solve very small problems); software engineer (patterns and architectures); security/privacy comparisons (I look for tools comparisons every day, they drive our daily choices); travelling (as soon as I could) who knows what else? Language skills I started learning english seriously when I began University, and as self-taught. So I often make some very big mistakes, and in most cases I am very insecure about by communication skills. One of the most common advice I have ever heard about languages is: \u0026ldquo;try\u0026rdquo;. So after followed my master degree completely in English, moved abroad working for six months in an international company, I was thinking about what could I do to continue improving it; I believe that leaving my \u0026ldquo;comfort zone\u0026rdquo; to connect myself with different people can only be helpful.\nOnline presence Every now and then, during my daily job or simply reading other authors, I often find people do what I would like, so why should I only watch other people doing, if I could? Maybe I am not so good at writing like others are, but it doesn\u0026rsquo;t mean I can\u0026rsquo;t try.\nFeedbacks By exposing myself to many and different people, I expose what I do to different comments. Maybe I can regret what I am saying but:\nCriticism is welcome.\nAll comments are welcome, but critics permit to grow up, to avoid mistakes already done. Also advices are very important, from everyone, all ages, all experiences.\nConclusions The best way to learn something is to play with it, in short:\n\u0026ldquo;The game is on\u0026rdquo;\n(cit. Sherlock).\n",
"ref": "/blog/why/"
},{
"title": "About",
"date": "",
"description": "",
"body": "Hi, I am Antonio, a polyglot Software Engineer.\nI like facing code challenges, learning programming languages and exploring software security, which is my secret hobby.\nI try to practice any kind of sport, from running to swimming, from soccer to yoga, and I have recently added boxe to the list :-).\nI would like to spend most of my time travelling, exploring the world. Next places I plan to visit: Norway, Spain, Portugal, Greece.\nIf you find some mistake, please forgive me, and let me know. I\u0026rsquo;m not a native English-speaker and I am still trying to improve my language skills (that\u0026rsquo;s one of the reason I started this project). The languages I would like to speak: Italian, English, French and Spanish.\n",
"ref": "/about/"
}]