niedziela, 13 grudnia 2015

Web Image Downloader - Header Retriever

Some time has passed so I decided to fill some more content to this marvelous blog. This time the idea is to create software that will be able to download images from websites. There are probably tons of software for doing that but let me play around for a while :]

Thats pretty much how it's supposed to work:

  • user enters website url to some field and clicks download button
  • program checks if that page exists and if so, places it on download list
  • content is being read from the website and strings matching img pattern extracted
  • each extracted url has to be checked to see if it exists and if so, how big the file is
  • files that will pass are displayed to user so he knows whats being downloaded
  • downloaded files go to folder specified by the user 

As I already traveled the route of extremely overengineering this, I decided to calm down and go as easy as I can and not skipping any unit testing, mocking the hell out of it.
First step is easy and clear, entered url either passes or not
To make those tests work I simply decided to check Uri.Scheme so if scheme matched desired ones the url passes if scheme doesn't match, url is null, whitespace, empty or just cannot by created by Uri.TryCreate then it doesn't. Simple as that. I thought about some url fixer, but that'll come later on.
Now the sweet thing from the title - HeaderRetriever. To get information about file size without actually downloading it I decided to go for headers. Part of it is also providing me with HttpStatusCode so I can first determine if I can work with that given url. To test it I decided to go for couple iterfaces and do some facades. Classes required for this to work are WebRequest and HttpWebResponse (as just WebResponse doesn't show the HttpStatusCode I want).
Here are the tests:

Now the fun part. As you may know or not, you can get that WebRequest using its static method Create, but I don't like it static, it's bad for testing and your teeth. So first step was to be able to inject IWebRequestCreator to my retriever. You can notice that in System.Net there's already IWebRequestCreate interface. Unfortunately it was forcing me to return WebRequest and I wanted the simpliest way so I've created that interface and decided to return another one IHttpWebRequest. That one exposes just two properties: Timeout, Method and allows me to get IHttpWebResponse, which I'll show in the moment. In matter of fact it'll be probably easier to show them now and describe what you see.

Just looking at the interfaces appears to be great way of understanding how they will work. I expose only what I need at the moment (there's small step in the future with Method property, as I'll use it soon for getting page content, but let it be). Concrete implementations are also quite simple. All I did here was passing original Request and Response into my Custom ones so they can work on them (thats kind of facade pattern if I'm right).
At this point testing was easy, I've created stubs for each of those interfaces so I could fully decide on the result I want and also decoupled this part from internet connection. Here is the complete HeaderRetriever:

Brak komentarzy:

Prześlij komentarz