[{"content":"Where ideas become words (maybe). I write about blockchain protocols, Web3 infrastructure, and production systems more broadly — plus whatever else I run into building software day to day.\n","date":"October 25, 2020","externalUrl":null,"permalink":"/","section":"Antomor","summary":"Where ideas become words (maybe). I write about blockchain protocols, Web3 infrastructure, and production systems more broadly — plus whatever else I run into building software day to day.\n","title":"Antomor","type":"page"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/blog/","section":"Blog","summary":"","title":"Blog","type":"blog"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/tags/blog/","section":"Tags","summary":"","title":"Blog","type":"tags"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/categories/development/","section":"Categories","summary":"","title":"Development","type":"categories"},{"content":"This post aims to describe the basic mechanisms behind iterators and generators.\nIterator protocol # As in many programming languages, Python allows you to iterate over a collection. The iteration mechanism is often useful when we need to scan a sequence, an 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 well-known iterables are lists, tuples, dictionaries, and ranges. In the iterator protocol, the iterable exposes an __iter__ method that returns an iterator object.\nIterator # The iterator is the data structure that allows scanning through the container. It could seem like a complication, but actually, with the separation of concerns, it lets the developer separate the concept of the 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 can take place at the same time, so keeping the iteration state in a different object is a must. The container is a collection of elements, while the iterator is a kind of handler for the container: it exposes the same elements (owned by the container) one by one, in a specific order. In the iterator protocol, the iterator exposes two methods: __iter__ and __next__. While the first one returns the object itself (which allows the use of both the container and the iterator in for and in statements), the latter returns the next item from the container. What makes the iterator end the iteration? The StopIteration exception.\nIterable and Iterator Examples # Below is an example of an iterator protocol implementation:\nAnd its usage:\nGenerator # Generators are methods with yield statements. The yield statement has the power to suspend the function\u0026rsquo;s execution and store its state, so that it can be resumed. Behind the scenes, Python returns control to the function\u0026rsquo;s caller and saves the function\u0026rsquo;s state; this way, at the next execution, the function will start where it left off, without the developer needing to worry about the function\u0026rsquo;s state. Generators ARE iterators, but not vice versa.\nHere is an example of a generator:\nand its usage:\nAsync generator # Like generators, they are async functions with a yield statement.\nConclusions # Iterators are iterables. Iterators are objects that implement the iterator protocol, consisting of 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, generators should be the preferred method due to their simplicity, while the protocol implementation gives much more control. Resources # Iterator types Generator types Yield expression Generators and iterators ","date":"October 25, 2020","externalUrl":null,"permalink":"/blog/python-iterators-generators/","section":"Blog","summary":"This post aims to describe the basic mechanisms behind iterators and generators.\nIterator protocol # As in many programming languages, Python allows you to iterate over a collection. The iteration mechanism is often useful when we need to scan a sequence, an operation that is very common in programming. In Python, the iterator protocol involves two components: an iterable and an iterator.\n","title":"Iterators \u0026 Generators in Python","type":"blog"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/tags/python/","section":"Tags","summary":"","title":"Python","type":"tags"},{"content":"","date":"October 25, 2020","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"April 11, 2020","externalUrl":null,"permalink":"/tags/angular/","section":"Tags","summary":"","title":"Angular","type":"tags"},{"content":"In many cases we need to change the content of a component dynamically — for instance, to allow the user to change view, or to let the children render data retrieved and processed by its parent component. Below, we are going to show some techniques for creating a component without deciding in advance how the data will be shown. According to the application\u0026rsquo;s needs, each technique has its own strengths, but all of them encourage component reusability. We are going to describe:\nContent projection Dynamic templates Dynamic component creation All the code is available on github and Stackblitz.\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 rendered in a certain section.\nFirst of all, we need to use the ng-content tag in the dynamic component. Then, when we use the component, we could include all the content we want within the new component tag. A more flexible way to use content projection can be achieved by using the class selector. In this case, the dynamic content specifies, using a class selector, where the content will be injected.\nNow, in the component user, we could include two elements that will be injected in the component. Dynamic Template # Dynamic template is very easy to use, but it comes with some problems in terms of flexibility, so it could be a good choice for simple mechanisms to be implemented. A typical example could be rendering one of two elements according to a condition.\nIt could also be very useful for avoiding repetition of template parts, by writing the HTML part once and using the template context to pass data to the template. Dynamic Component creation # Dynamic component creation is by far the most flexible technique to use, because it allows you to choose the instant at which the component will be created. On the other hand, it is the most complicated to write, even if, after the first few times, everything becomes clearer and easier to repeat.\nTo implement this technique we need:\na container tag directive, used to reference the container from within the parent component, to tag where the new child component will be rendered. from the parent component, we need to reference the container using the @ViewChild annotation. in the parent component, we use the ComponentFactoryResolver to create an instance of the component to be created Conclusions # As in many other cases in programming, there are different ways to accomplish the same task, but it often depends on what the software requirements are and what result we want to achieve. This article isn\u0026rsquo;t intended to be a detailed guide to these techniques, but only a general description of some of the possibilities Angular offers for dynamically rendering content within a component.\nResources # ng-content ng-template, ng-container and ng-template-outlet Dynamic Components ","date":"April 11, 2020","externalUrl":null,"permalink":"/blog/angular-dynamic-content/","section":"Blog","summary":"In many cases we need to change the content of a component dynamically — for instance, to allow the user to change view, or to let the children render data retrieved and processed by its parent component. Below, we are going to show some techniques for creating a component without deciding in advance how the data will be shown. According to the application’s needs, each technique has its own strengths, but all of them encourage component reusability. We are going to describe:\n","title":"Angular Dynamic Content","type":"blog"},{"content":"","date":"April 11, 2020","externalUrl":null,"permalink":"/tags/dev/","section":"Tags","summary":"","title":"Dev","type":"tags"},{"content":"","date":"April 11, 2020","externalUrl":null,"permalink":"/tags/tutorial/","section":"Tags","summary":"","title":"Tutorial","type":"tags"},{"content":" 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 a Content-Security-Policy HTTP header or using an 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, each composed of the area in which the rule is applied and the rule itself. The policy directive default-src 'self' says to load all content from the site\u0026rsquo;s origin, while if we want to load 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 which domains are entitled to access the resource. Let\u0026rsquo;s have a look at the following scenario:\nWe 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:\nAccess-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 set, 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.\nWe 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, the web service exposed on domain-b.com must enable CORS, but that might not be enough. If we have configured CSP on the domain-a.com web application, we also need to relax the connect-src policy directive to allow https://domain-b.com. So, to properly run the previous scenario:\nEnable 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 ","date":"April 11, 2020","externalUrl":null,"permalink":"/blog/csp-and-cors/","section":"Blog","summary":"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 a Content-Security-Policy HTTP header or using an HTML meta tag.\nHTTP header:\nContent-Security-Policy: policy HTML Meta tag:\n\u003cmeta http-equiv=\"Content-Security-Policy\" content=\"policy\"\u003e A policy describes a set of directives, each composed of the area in which the rule is applied and the rule itself. The policy directive default-src 'self' says to load all content from the site’s origin, while if we want to load content from the site and from another trusted domain, the policy would be Content-Security-Policy: default-src 'self' *.trusted.com.\n","title":"CSP and CORS","type":"blog"},{"content":"","date":"April 11, 2020","externalUrl":null,"permalink":"/tags/sec/","section":"Tags","summary":"","title":"Sec","type":"tags"},{"content":"","date":"April 11, 2020","externalUrl":null,"permalink":"/categories/security/","section":"Categories","summary":"","title":"Security","type":"categories"},{"content":"Any modern web application needs, sooner or later, to perform some http requests to retrieve data. Below, I\u0026rsquo;ll describe some common scenarios and how to perform such requests using RxJS.\nSingle request # The most common scenario, no special rxjs handling needed, since 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:\nWe 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 of applying the solution described in point 2 word-for-word, 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 may never have used it, so let\u0026rsquo;s do an example.\nOur friend is watching a race on TV, but we are not fans, so we are not interested in who wins; the only thing we want to know is when the race 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. In practice, it receives an array of observables, and we can then subscribe to an array of results having the same array index as 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;\nThis leads to a common mistake. What if a runner is disqualified? The race is still valid for the remaining runners, right? Well, by default, forkJoin succeeds 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 succeeds 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, the results are filled differently according to the responses\u0026rsquo; status, and if a request fails, we have undefined in the corresponding item among the results. So if 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.\nconcatMap mergeMap switchMap Assuming we want to perform 2 requests:\nmergeMap: the second request starts as soon as possible, without waiting for the end of the first one, so the order of the subscriptions isn\u0026rsquo;t guaranteed (if important, it must be handled manually 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 request 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 may already know, performing a subscription within a subscribe is very bad practice and MUST be absolutely avoided. This looks very similar to the callback hell problem, nowadays fortunately almost forgotten.\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 wanted to compose the response using both the first response and the responses coming from 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 failure should be handled individually If we have a request that uses the response of another request, it\u0026rsquo;s likely that we need switchMap NO Subscribe-in-Subscribe Resources # RxJS LearnRxJS Angular HTTP guide ","date":"April 9, 2020","externalUrl":null,"permalink":"/blog/angular-rxjs-http-requests/","section":"Blog","summary":"Any modern web application needs, sooner or later, to perform some http requests to retrieve data. Below, I’ll describe some common scenarios and how to perform such requests using RxJS.\nSingle request # The most common scenario, no special rxjs handling needed, since 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.\n","title":"Angular and Rxjs Http Requests: Common scenarios","type":"blog"},{"content":"","date":"April 9, 2020","externalUrl":null,"permalink":"/tags/rxjs/","section":"Tags","summary":"","title":"Rxjs","type":"tags"},{"content":"","date":"March 14, 2020","externalUrl":null,"permalink":"/tags/git/","section":"Tags","summary":"","title":"Git","type":"tags"},{"content":"Some time ago we needed to create a new product that shares many features with the existing one. The first idea was to extract some of the code into a library, to be then imported and used independently in the two projects.\nAfter creating the repository for the library, the first thing I would have done was copy the files from one repo to another. Well, it works like a charm, it\u0026rsquo;s fast, and it doesn\u0026rsquo;t require any particular expertise — a normal drag-and-drop operation. What\u0026rsquo;s more? It could be a very effective approach, but \u0026hellip;\nDuring a PR review, I learnt there was a clever way to perform this operation, and I wasn\u0026rsquo;t even aware such a thing was possible before:\nMoving files from one git repository to another retaining the history.\nMoving 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 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\u0026rsquo;s blog article):\nAfter 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 in the repository. So, to recap:\nDownload the script, and change it according to 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:\nbash $(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 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 can be very useful.\nTip: The process could seem counterintuitive, so I suggest giving it a try with a test repository. After the first time, everything will be much clearer.\nResources # A useful guide from @ayushya on Medium Tom Hacohen explains how to git move single files ","date":"March 14, 2020","externalUrl":null,"permalink":"/blog/git-move-file-with-history/","section":"Blog","summary":"Some time ago we needed to create a new product that shares many features with the existing one. The first idea was to extract some of the code into a library, to be then imported and used independently in the two projects.\nAfter creating the repository for the library, the first thing I would have done was copy 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 more? It could be a very effective approach, but …\n","title":"Git: Move Files Retaining History","type":"blog"},{"content":"","date":"December 28, 2019","externalUrl":null,"permalink":"/tags/mongodb/","section":"Tags","summary":"","title":"Mongodb","type":"tags"},{"content":"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 the possible issue, we discovered the bottleneck: the database. The solution was to restructure the data to make it consumable from a web page.\nAlthough I had sometimes used the SQL Server profiler, I had no experience with the MongoDB profiler, so here are the steps involved in analysing a MongoDB query.\nIt doesn\u0026rsquo;t apply to our case, but in many situations performance problems are related to missing or wrongly implemented MongoDB Indexes.\nEnable 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:\n0 - 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 it can affect MongoDB performance.\nRetrieve last query profile # Once profiling is enabled, it is possible to retrieve the last profiled query (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 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 also available on collection and cursor.\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:\nqueryPlanner - 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 were we able to improve its performance.\nNot our case, but it\u0026rsquo;s worth remembering that performance problems are often associated with missing or wrongly implemented indexes. If so, please have a look at MongoDB Indexes.\nResources # MongoDB database profiler Explain results MongoDB Indexes ","date":"December 28, 2019","externalUrl":null,"permalink":"/blog/mongodb-query-profiler/","section":"Blog","summary":"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 the possible issue, we discovered the bottleneck: the database. The solution was to restructure the data to make it consumable from a web page.\nAlthough I had sometimes used the SQL Server profiler, I had no experience with the MongoDB profiler, so here are the steps involved in analysing a MongoDB query.\n","title":"Mongodb Query Profiler","type":"blog"},{"content":"","date":"December 28, 2019","externalUrl":null,"permalink":"/tags/nosql/","section":"Tags","summary":"","title":"Nosql","type":"tags"},{"content":"When I started this blog, I evaluated many options:\nblogging platform vs static-generated website self-hosted vs hosted solutions costs and many more. I ended up trying to build something very simple, consisting of a static website hosted on GitHub Pages. With this solution, I have been able to cut the cost of any hosting solution, since, being a dev, I am quite comfortable writing in a text editor. But soon some problems arose.\nI discovered it was impossible to harden the server to customize the response headers. Why should someone customize the response headers? The response to that question is:\n\u0026ldquo;When she/he encounters securityheaders.com and she/he gets an F\u0026rdquo;.\nI believe that many people do not apply the required security constraints due to the barriers they encounter in understanding the reasoning behind them. On the contrary, securityheaders.com did a very good job of letting people understand what is wrong with their 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:\nReferrer leakage\nWith the Referrer-Policy, it is possible to instruct the browser not to send the referrer header along with requests. XSS (Cross-site scripting)\nUsing Content-Security-Policy instructs the browser about what content will be rendered on a page Along with the 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\nThe X-Frame-Options header can be used to instruct the browser whether it is allowed to render content in a frame. Tab nabbing\nAlong with other mechanisms that can be used to mitigate this attack, setting the Referrer-Policy header can also be useful. and many more.\nFor a much more detailed description of the risks associated with HTML5 pages, please have a look at the OWASP HTML5 Security Cheat Sheet.\nHow # So, back to this blog: how is it possible to reach an A+ report while running a static website on GitHub Pages? No, you don\u0026rsquo;t need to pay anything to improve your website\u0026rsquo;s 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.\nBelow is 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 his post, where he describes exactly what each header is used for. I strongly recommend having a look at the 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 ","date":"December 26, 2019","externalUrl":null,"permalink":"/blog/security-headers-on-static-websites/","section":"Blog","summary":"When I started this blog, I evaluated many options:\nblogging platform vs static-generated website self-hosted vs hosted solutions costs and many more. I ended up trying to build something very simple, consisting of a static website hosted on GitHub Pages. With this solution, I have been able to cut the cost of any hosting solution, since, being a dev, I am quite comfortable writing in a text editor. But soon some problems arose.\n","title":"Security Headers on Static Websites","type":"blog"},{"content":"","date":"December 13, 2019","externalUrl":null,"permalink":"/tags/ci/cd/","section":"Tags","summary":"","title":"Ci/Cd","type":"tags"},{"content":"","date":"December 13, 2019","externalUrl":null,"permalink":"/tags/docker/","section":"Tags","summary":"","title":"Docker","type":"tags"},{"content":"","date":"December 13, 2019","externalUrl":null,"permalink":"/tags/gitlab/","section":"Tags","summary":"","title":"Gitlab","type":"tags"},{"content":"","date":"December 13, 2019","externalUrl":null,"permalink":"/tags/nginx/","section":"Tags","summary":"","title":"Nginx","type":"tags"},{"content":"In the last few projects, I started using GitLab, not only as a git repository server, but also as a DevOps platform. So here I am going to describe a very simple architecture for deploying a single-page application using Docker, docker-compose, and nginx. In this specific project I also used dotnet-core for the back-end API and VueJS as the 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:\nFront-end Back-end Deploy I considered using a single repo to maintain all the codebase, but I ended up with this structure for the following reasons:\nOften the teams working on back-end and front-end are not the same, so this way they are completely independent from each other This way the project structure can be reused with any framework/language combination We are almost separating the local development phase from the DevOps phase (apart from the inclusion of the gitlab-ci.yml files). Front-end static files generation # I used VueJS and the related vue-cli tools to generate the static files, but it doesn\u0026rsquo;t really matter for 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 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 we make use of dotnet-core, we need to build the project, so this step could be unnecessary if you choose a language that doesn\u0026rsquo;t require compilation (e.g. Node.js, 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.\nIt 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 produce their own artifacts. It\u0026rsquo;s time to let them talk!\nDeploy project # Project structure # |__ api | |__ Dockerfile |__ nginx | |__ nginx.conf |__ gitlab-ci.yml |__ docker-compose.yml This project performs the following steps:\nRetrieve 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 folder to the nginx container ./api/ the folder containing the Dockerfile used to set up the dotnet APIs container. For completeness, here is the content of the Dockerfile used to run the dotnet APIs.\n# Build runtime image FROM microsoft/dotnet:aspnetcore-runtime WORKDIR /app COPY . . 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 intended as an example only. For nginx production configuration, please refer to the following resources:\nSsl-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 into the script commands:\nRetrieve the front-end artifacts by using the GitLab API (for non-enterprise users) It also requires setting the PRIVATE-TOKEN variable with a personal access token, which 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 repository 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","date":"December 13, 2019","externalUrl":null,"permalink":"/blog/gitlab-cd/","section":"Blog","summary":"In the last few projects, I started using GitLab, not only as a git repository server, but also as a DevOps platform. So here I am going to describe a very simple architecture for deploying a single-page application using Docker, docker-compose, and nginx. In this specific project I also used dotnet-core for the back-end API and VueJS as the front-end framework, but it is language-agnostic, meaning that you can replace whatever back-end or front-end you prefer.\n","title":"SPA deployment with GitLab","type":"blog"},{"content":"Web extensions or browser plugins can be used to improve browser functionalities. The following examples summarize the different goals they can have:\nno-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:\nManifest.json — it is the only mandatory file, and it describes the extension itself. It acts as an entry point for the browser, declaring which files/resources/permissions will be used.\nBackground scripts — they contain the logic that is not strictly related to a single web page. They are loaded when the extension is loaded and remain active until the extension is disabled or uninstalled.\nContent scripts — unlike background scripts, they are loaded into web pages, so they can manipulate the DOM exactly like a normal script can.\nUI components — they include all the parts that allow a user to interact with the extension, by means of an HTML document. There are three different UI components:\nsidebar popup options page Web-accessible resources — they include all the resources that are made available to the scripts (e.g. HTML, images, JS, CSS)\nExtension pages - They are additional pages used to handle specific user interactions.\nWeb-extension toolbox # As with many browser APIs, the web extension APIs can also behave differently according to the browser on which they are executed. In case of cross-browser development, the web-extension polyfill developed by Mozilla could be handy.\nFurthermore, to ease the development process, there is also the web-extension toolbox and its related yeoman generator. Among other things, it provides the following functionalities:\nCompiles the extension via webpack to dist/\u0026lt;vendor\u0026gt; Watches all extension files and re-compiles on demand Reloads the extension or extension page as soon as something changes After answering 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\u0026rsquo;ve already started mine ;-)\nResources # MDN Browser Extensions webextension-toolbox Mozilla web-ext ","date":"November 20, 2019","externalUrl":null,"permalink":"/blog/browser-extension/","section":"Blog","summary":"Web extensions or browser plugins can be used to improve browser functionalities. The following examples summarize the different goals they can have:\nno-script - to block script served from not-trusted domains ublock Origin - it is “a wide-spectrum blocker” 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","title":"Browser Extension Development","type":"blog"},{"content":"","date":"November 20, 2019","externalUrl":null,"permalink":"/tags/browser-plugin/","section":"Tags","summary":"","title":"Browser Plugin","type":"tags"},{"content":"","date":"November 20, 2019","externalUrl":null,"permalink":"/tags/web-extension/","section":"Tags","summary":"","title":"Web-Extension","type":"tags"},{"content":" 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 remember that bugs cannot be entirely eliminated from software — instead, they must be discovered as soon as possible.\nThe higher the time passed since the bug came into the system, the higher the cost to fix it.\nSo 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.\nI am going to focus on the developer\u0026rsquo;s point of view: what can a developer 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 address this gap from now on.\nAlthough I have been programming for about 5 years, I think I have very little practical experience with software testing. Please don\u0026rsquo;t misjudge me for that. In the past I wrote some tests, but usually while working in an already set-up environment, writing small tests for the functionality I was adding to the system. Here I am talking 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 into the details of a specific framework (hurrah, practice!) in a dedicated article, but not here.\nKeywords # Unit test # Unit test refers to a single unit of code. What actually is a unit? According to the paradigm used, a unit of code can be a function or a class in the 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, in particular, the corner cases, in a defensive programming manner. Why? Because, as a developer, you will run through 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 integration testing should not be overlooked, since with unit testing alone it is not possible to identify defects at the interface level.\nMock # Mocking during testing is fundamental. It is the process of creating an object that can simulate the behavior of a real object. This is necessary because, in the real world, a unit is often composed of or depends on other units. To make sure the code under test is isolated, and to avoid side effects that 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 occurring externally to the unit being tested.\nTDD # Test-Driven Development is a software development process which involves the creation of the test before actually implementing the functionality. The process involves the following steps:\nVerify whether the current design fits well 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 (clean up if necessary, remove duplications, etc.). Run the tests. The upside of the process is highlighted by steps 1 and 4: step 1 makes it possible to refactor the existing code without being afraid of it and without losing confidence; step 4 is useful for keeping the code clean, improving readability and maintainability; it can also, in some cases, be useful for trying to figure out whether there is a solution that improves performance, and such an operation could be performed in 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, who can define the specification of the tests in a domain-specific language, which developers can then translate (also by means of automated tools) into a specific programming language.\nConclusion # If I\u0026rsquo;m not the only person in the world who hasn\u0026rsquo;t yet established a real TDD strategy in their daily job, I strongly recommend giving it a try. Keep in mind that a very robust system should be tested as much as possible, from every perspective, both functional and non-functional, taking into account also features too often overlooked, like security and performance; so please also consider investigating performance testing and security testing — I will try to describe them in a related post.\n","date":"August 25, 2019","externalUrl":null,"permalink":"/blog/lets-test/","section":"Blog","summary":"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 remember that bugs cannot be entirely eliminated from software — instead, they must be discovered as soon as possible.\n","title":"Let's Test","type":"blog"},{"content":"","date":"August 25, 2019","externalUrl":null,"permalink":"/tags/test/","section":"Tags","summary":"","title":"Test","type":"tags"},{"content":"Here in this post, I am going to explain why I am starting to write something on the internet and what I am going to share. I am well aware that there are many sites today describing almost everything, but these are some of the reasons that drive me at this point:\nto improve my language skills; to improve my online presence; to receive feedback (feedback is the key to growing); to share what I do (and how — I am also going to list some of my biggest mistakes). And what about the content?\nWell, regarding the content, I am not completely sure what I am going to describe, but approximately it could be:\ncoding (small snippets of code that solve very small problems); software engineering (patterns and architectures); security/privacy comparisons (I look for tool comparisons every day — they drive our daily choices); travelling (as soon as I can) who knows what else? Language skills # I started learning English seriously when I began university, and I am self-taught. So I often make some very big mistakes, and in most cases I am quite insecure about my communication skills. One of the most common pieces of advice I have ever heard about languages is: \u0026ldquo;try\u0026rdquo;. So, after completing my master\u0026rsquo;s degree entirely in English and moving abroad to work for six months at an international company, I was thinking about what I could do to keep improving it; I believe that leaving my \u0026ldquo;comfort zone\u0026rdquo; to connect with different people can only be helpful.\nOnline presence # Every now and then, during my daily job or simply while reading other authors, I often find people doing what I would like to do — so why should I only watch other people do it, if I could do it myself? Maybe I am not as good at writing as others are, but that doesn\u0026rsquo;t mean I can\u0026rsquo;t try.\nFeedback # By exposing myself to many different people, I expose what I do to different opinions. Maybe I\u0026rsquo;ll regret what I\u0026rsquo;m saying, but:\nCriticism is welcome.\nAll comments are welcome — criticism helps me grow and avoid mistakes I\u0026rsquo;ve already made. Advice is also very important, from everyone, all ages, all experience levels.\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","date":"April 14, 2019","externalUrl":null,"permalink":"/blog/why/","section":"Blog","summary":"Here in this post, I am going to explain why I am starting to write something on the internet and what I am going to share. I am well aware that there are many sites today describing almost everything, but these are some of the reasons that drive me at this point:\nto improve my language skills; to improve my online presence; to receive feedback (feedback is the key to growing); to share what I do (and how — I am also going to list some of my biggest mistakes). And what about the content?\n","title":"Getting Started With My Website :-)","type":"blog"},{"content":"","date":"April 14, 2019","externalUrl":null,"permalink":"/categories/other/","section":"Categories","summary":"","title":"Other","type":"categories"},{"content":"","date":"April 14, 2019","externalUrl":null,"permalink":"/tags/personal/","section":"Tags","summary":"","title":"Personal","type":"tags"},{"content":"Hi, I\u0026rsquo;m Antonio — a Staff / Tech Lead Software Engineer, building software since 2013 and focused on blockchain protocols and Web3 infrastructure since 2021.\nWhat I do # System architecture. I design and own systems end to end — architecture, implementation, and how the pieces fit together — rather than just one layer of a larger system.\nTechnical leadership. Leading a project means owning the hard calls — what to build, what to defer, where the risk actually is — and making sure the team ships with confidence, not just speed.\nSecurity-minded engineering. Security is a habit built into how I design, not a review bolted on afterward — audits and production hardening as part of the process, not an afterthought.\nBlockchain \u0026amp; Web3 # This has been my focus since 2021: protocol architecture, smart contracts, and the off-chain infrastructure that supports them, built and shipped to production with external audits along the way.\nFor the full role-by-role history — companies, titles, and years — see my LinkedIn profile.\nOpen to # Remote roles, based in Italy — blockchain protocol / Web3 infrastructure roles first, and staff or lead engineering roles more broadly where architecture, ownership, and security rigor matter.\nOutside of work # I run, do yoga and boxing, and I\u0026rsquo;m always planning the next trip — Norway, Spain, Portugal, and Greece are next on the list. Non-native English speaker, still working on French and Spanish too — if you spot a mistake, let me know.\n","date":"June 24, 2017","externalUrl":null,"permalink":"/about/","section":"Antomor","summary":"Hi, I’m Antonio — a Staff / Tech Lead Software Engineer, building software since 2013 and focused on blockchain protocols and Web3 infrastructure since 2021.\nWhat I do # System architecture. I design and own systems end to end — architecture, implementation, and how the pieces fit together — rather than just one layer of a larger system.\n","title":"About","type":"page"},{"content":"Get in touch at dev@antomor.com, or find me on GitHub and LinkedIn.\n","externalUrl":null,"permalink":"/contact/","section":"Antomor","summary":"Get in touch at dev@antomor.com, or find me on GitHub and LinkedIn.\n","title":"Contact","type":"page"}]