Fiddler In Action: Mocking And Manipulating API Behavior With A Local Proxy Server – Part 5

In this five-part article series, you learn how to manipulate your API behavior with a local proxy server. So far, this series has covered an introduction, taught you how to set up and configure Charles Proxy, and you have seen it in action. After presenting the Fiddler setup, we will now take a look at it in action.

In this article:

Mission 1: Testing the Frontend Against Various API Responses

The todo demo API returns a JSON array with three objects, each with an id and title property. To demonstrate how to manipulate Fiddler’s responses, we will change a single object’s title to a very long one. As in Charles Proxy, we can do so via automatic breakpoints after each response. In the menu bar click “Rules” → “Automatic Breakpoints” → “After Responses”.

When triggering a new request, the response is halted, and we can modify it on our behalf.

Instead of editing the response body directly, you could also choose a predefined response from a list, such as different status code responses. Here you can see the result:

As you see, this requires fewer steps to set up than the same result in Charles Proxy. The comfort comes at the price of some flexibility, though – which should be no problem in most cases.

Mission 2: Developing Against a Wrong API Implementation

Breakpoints are great if you want to do some quick tests. However, if you are trying to permanently change a response, maybe until a bug in the API has been fixed, breakpoints are not practical. We would like Fiddler to always respond with a predefined response.

Fiddler calls this feature “AutoResponder”.

Before we activate it, we have to store a real response and modify it according to our needs. To do so, select the request from the list, right-click and then select “Save” → “Response” → “Entire Response” from the context menu.

After saving the response we’ll edit it with any text editor to fit our needs. In this case, we want each object to contain an additional property done.

				
					HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Cache-Control,access_token
Content-Type: application/json
Content-Length: 85
Etag: "1241236335"
Vary: Accept-Encoding
Date: Mon, 14 Oct 2019 13:20:27 GMT
Via: 1.1 vegur
Cache-Control: no-cache

[{"id":"1","title":"Todo 1","done":false},{"id":"2","title":"Todo 2","done":false},{"id":"3","title":"Todo 3","done":true}]
				
			

Next, we have to tell Fiddler’s AutoResponder to use this file for the given request. This is done by selecting the “AutoResponder” tab on the right side and checking “Enable rules”. Now we can drag and drop the request into the big text area and edit the rule to “Find a file…”. We also need to check the “Unmatched requests passthrough”. Otherwise, all non-matches requests will drop.

After creating and changing the file and applying the autoresponder rules, we are now reloading the frontend to see the result.

As the image shows, nothing shows up. There is no CORS error in the console or anything else suspicious. Within Fiddler, everything looks fine as well. Let’s check the Chrome dev tools:

Before we take a look at the solution, we want to explain a major difference between Charles and Fiddler. In Charles, we had only the option to save the response body. This resulted in missing CORS headers when the response was mapped to a file.

In Fiddler, we had the choice between “Save response body” and “Save entire response”. We chose the latter to circumvent the problem of missing headers. However, this led to fixed headers, including the “Content-Length” header – which needs to get adjusted since the response body size changed!

Don’t worry! We don’t have to calculate this. We can just serve it wrong once and then look at Fiddler’s recording, and we will see the actual length in the “Body” column:

Again, we edit the saved response as follows:

				
					HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Cache-Control,access_token
Content-Type: application/json
Content-Length: 123
Etag: "1241236335"
Vary: Accept-Encoding
Date: Mon, 14 Oct 2019 13:20:27 GMT
Via: 1.1 vegur
Cache-Control: no-cache

[{"id":"1","title":"Todo 1","done":false},{"id":"2","title":"Todo 2","done":false},{"id":"3","title":"Todo 3","done":true}]
				
			

Save and reload:

 

Mission accomplished. That was a bit easier compared to Charles as we were able to save the headers as well and did not have them added partially by a Rewrite tool as in Charles. Sure, we had to change the Content-Length header manually. However, that was much less of a hassle than the rewrite marathon.

Mission 3: Developing against an incomplete API

Like every todo app, ours needs the most used feature: adding todos. Unfortunately, the API has not yet implemented the respective endpoint. Let’s fake it! The additional target will be POST /api/todo next to the already existing GET /api/todo.

We are using the AutoResponder for this task. At first, we create a Fiddler record by triggering the request from the frontend. That leads to a “400 Bad request” response that’s ok for now. We just want the record in Fiddler to drag and drop it to the AutoResponder. Even though we already had a matching rule for this path, AutoResponder combined it this time with a method role as well!

Since we don’t have a recorded response template for this route, we copy the one from the GET method, replace the response body, and save the file under a different name. Here is the result (with adjusted Content-Length):

				
					HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
X-Powered-By: Express
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Cache-Control,access_token
Content-Type: application/json
Content-Length: 42
Etag: "1241236335"
Vary: Accept-Encoding
Date: Mon, 14 Oct 2019 13:20:27 GMT
Via: 1.1 vegur
Cache-Control: no-cache

[{"id":"4","title":"Todo 4","done":false}]
				
			

That’s the result in the frontend after adding two items:

It’s working! Do you remember the issues with Charles Proxy? We had to choose another endpoint path because Charles cannot to map different local files to different request methods. No problem for Fiddler, which is a huge plus in this mission!

Mission 4: Offline Development Against a Remote API

Recap: we have a working remote API and want it to be faked by our local proxy to be independent of the original during development. This is especially valuable when you are missing a stable internet connection.

A naive solution would be to drag and drop each possible path/method combination into the AutoResponder and match it against the according to the stored response.

Unfortunately, this is exactly what we need to do. There is no option to “batch”-map a whole parent path to recorded responses on your hard drive. If your API is big, you should only map those requests in AutoResponder, which are necessary for you to finish your current or next task.

In this demo, it’s easy. There are only two endpoints, and we have them already covered at the AutoResponder. So let us test it by disabling the internet.

And now, we have the same problem as we had with Charles Proxy. Fiddler also tries to establish a CONNECT request to the server. However, in Fiddler, we can work around this by unchecking the AutoResponder checkbox “Unmatched requests passthrough”.

In addition to the POST request, we also needed to map the OPTIONS request (CORS preflight request). So the complete AutoResponder settings are looking as follows:

With this configuration, we can develop against a remote API over HTTPS while being offline! This is another significant advantage of Fiddler over Charles Proxy.

Conclusion

Fiddler passed 4 of 4 missions. It is straightforward and effective to change response, add endpoints, and set up automatic response mappings. The only functional flaw compared to Charles Proxy is the inability to batch map a huge set of requests.

However, we did not cover the underlying script support (“Fiddler Script”), a powerful tool to inspect requests/responses and apply them programmatically With Fiddler Script we can even add new configuration menu entries.

Fiddler’s succession candidate, Fiddler Everywhere, has a very clean UI and is being built natively for each platform (.exe/.AppImage/.dmg) without any further dependencies. But it still lacks fundamental features. It’s worth checking it out from time to time!

Free
Newsletter

Current articles, screencasts and interviews by our experts

Don’t miss any content on Angular, .NET Core, Blazor, Azure, and Kubernetes and sign up for our free monthly dev newsletter.

Related Articles
.NET
Incremental Roslyn Source Generators in .NET 6: Adapt Code Generation Based on Project Dependencies – Part 5
The Roslyn Source Generator, implemented in the previous articles of the series, emits some C# code without looking at the dependencies of the current .NET (Core) project. In this article our DemoSourceGenerator should implement a JsonConverter, but only if the corresponding library (e.g. Newtonsoft.Json) is referenced by the project.
08.07.2022
Angular
Configuring Lazy Loaded Angular Modules
Making our Angular modules configurable is an important step in building a reusable architecture. Having used Angular for a while you might be familiar with the commonly used forRoot() and forChild() functions, that some modules provide you with. But what is the best way to provide configuration in these cases?
16.06.2022
Angular
Master Web Component Forms Integration – with Lit and Angular
When a company has cross-framework teams, it is a good choice to use Web Components to build a unified and framework-independent component library. However, some pitfalls are to consider when integrating these components into web forms. Therefore, for a better understanding, we will look at two possible approaches and try to integrate them into an Angular form as an example.

Notice: All code samples are available on Github!
09.06.2022