├── .gitignore
├── .travis.yml
├── src
├── main
│ └── java
│ │ └── de
│ │ └── sstoehr
│ │ └── harreader
│ │ ├── model
│ │ ├── HttpMethod.java
│ │ ├── Har.java
│ │ ├── HttpStatus.java
│ │ ├── HarQueryParam.java
│ │ ├── HarHeader.java
│ │ ├── HarCreatorBrowser.java
│ │ ├── HarPageTiming.java
│ │ ├── HarPostData.java
│ │ ├── HarPostDataParam.java
│ │ ├── HarContent.java
│ │ ├── HarPage.java
│ │ ├── HarLog.java
│ │ ├── HarCookie.java
│ │ ├── HarTiming.java
│ │ ├── HarCache.java
│ │ ├── HarEntry.java
│ │ ├── HarResponse.java
│ │ └── HarRequest.java
│ │ ├── HarReaderException.java
│ │ ├── jackson
│ │ ├── MapperFactory.java
│ │ ├── DefaultMapperFactory.java
│ │ ├── ExceptionIgnoringIntegerDeserializer.java
│ │ └── ExceptionIgnoringDateDeserializer.java
│ │ ├── HarReaderMode.java
│ │ └── HarReader.java
└── test
│ ├── java
│ └── de
│ │ └── sstoehr
│ │ └── harreader
│ │ ├── model
│ │ ├── HarQueryParamTest.java
│ │ ├── HarTest.java
│ │ ├── HttpStatusTest.java
│ │ ├── AbstractMapperTest.java
│ │ ├── HarHeaderTest.java
│ │ ├── HarCreatorBrowserTest.java
│ │ ├── HarPostDataParamTest.java
│ │ ├── HarContentTest.java
│ │ ├── HarPostDataTest.java
│ │ ├── HarCookieTest.java
│ │ ├── HarPageTest.java
│ │ ├── HarCacheTest.java
│ │ ├── HarPageTimingTest.java
│ │ ├── HarTimingTest.java
│ │ ├── HarEntryTest.java
│ │ ├── HarResponseTest.java
│ │ ├── HarLogTest.java
│ │ └── HarRequestTest.java
│ │ └── HarReaderTest.java
│ └── resources
│ ├── sstoehr.har
│ ├── sstoehr.invalid-date.har
│ └── sstoehr.invalid-integer.har
├── LICENSE.md
├── README.md
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.iml
3 | target/
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - openjdk7
5 | - oraclejdk8
6 | script: "mvn verify -B"
7 | after_success:
8 | - mvn cobertura:cobertura coveralls:report
9 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HttpMethod.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | public enum HttpMethod {
4 | GET, POST, PUT, HEAD, PROPFIND, OPTIONS, REPORT, DELETE, CONNECT, TRACE, CCM_POST;
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/HarReaderException.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader;
2 |
3 | public class HarReaderException extends Exception {
4 |
5 | public HarReaderException(Throwable cause) {
6 | super(cause);
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/jackson/MapperFactory.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.jackson;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import de.sstoehr.harreader.HarReaderMode;
5 |
6 | public interface MapperFactory {
7 |
8 | ObjectMapper instance(HarReaderMode mode);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/HarReaderMode.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader;
2 |
3 | public enum HarReaderMode {
4 |
5 | /**
6 | * Using strict mode enforces some rules.
7 | * When trying to open an invalid HAR file an exception will be thrown.
8 | */
9 | STRICT,
10 |
11 | /**
12 | * Using lax mode you are able to read even invalid HAR files.
13 | * Currently lax mode allows:
14 | *
15 | * - invalid date formats
16 | *
17 | */
18 | LAX;
19 | }
20 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarQueryParamTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | public class HarQueryParamTest extends AbstractMapperTest {
6 |
7 | @Override
8 | public void testMapping() {
9 | HarQueryParam queryParam = map("{\"name\": \"aName\", \"value\":\"aValue\", \"comment\": \"My comment\"}", HarQueryParam.class);
10 |
11 | Assert.assertEquals("aName", queryParam.getName());
12 | Assert.assertEquals("aValue", queryParam.getValue());
13 | Assert.assertEquals("My comment", queryParam.getComment());
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HarTest extends AbstractMapperTest{
7 |
8 | @Test
9 | public void testLogNull() {
10 | Har har = new Har();
11 | har.setLog(null);
12 | Assert.assertNotNull(har.getLog());
13 | }
14 |
15 | @Override
16 | public void testMapping() {
17 | Har har = map("{\"log\": {}}", Har.class);
18 | Assert.assertNotNull(har.getLog());
19 |
20 | har = map(UNKNOWN_PROPERTY, Har.class);
21 | Assert.assertNotNull(har);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HttpStatusTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HttpStatusTest {
7 |
8 | @Test
9 | public void test302() {
10 | Assert.assertEquals(HttpStatus.FOUND, HttpStatus.byCode(302));
11 | }
12 |
13 | @Test
14 | public void testInvalidCode() {
15 | Assert.assertEquals(HttpStatus.UNKNOWN_HTTP_STATUS, HttpStatus.byCode(0));
16 | Assert.assertEquals(HttpStatus.UNKNOWN_HTTP_STATUS, HttpStatus.byCode(1000));
17 | Assert.assertEquals(HttpStatus.UNKNOWN_HTTP_STATUS, HttpStatus.byCode(-999));
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/AbstractMapperTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 |
7 | public abstract class AbstractMapperTest {
8 |
9 | protected final static String UNKNOWN_PROPERTY = "{\"unknownProperty\":\"value\"}";
10 |
11 | @Test
12 | public abstract void testMapping();
13 |
14 | public T map(String input, Class tClass) {
15 | ObjectMapper mapper = new ObjectMapper();
16 | try {
17 | return mapper.readValue(input, tClass);
18 | } catch (Exception e) {
19 | Assert.fail(e.getMessage());
20 | }
21 | return null;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarHeaderTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | public class HarHeaderTest extends AbstractMapperTest {
6 |
7 | @Override
8 | public void testMapping() {
9 | HarHeader header = map("{\"name\":\"aName\",\"value\":\"aValue\",\"comment\":\"my comment\"}", HarHeader.class);
10 |
11 | Assert.assertNotNull(header);
12 | Assert.assertEquals("aName", header.getName());
13 | Assert.assertEquals("aValue", header.getValue());
14 | Assert.assertEquals("my comment", header.getComment());
15 |
16 | header = map(UNKNOWN_PROPERTY, HarHeader.class);
17 | Assert.assertNotNull(header);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarCreatorBrowserTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | public class HarCreatorBrowserTest extends AbstractMapperTest {
6 |
7 | @Override
8 | public void testMapping() {
9 | HarCreatorBrowser creatorBrowser = map("{\"name\":\"aName\",\"version\":\"aVersion\",\"comment\":\"my comment\"}", HarCreatorBrowser.class);
10 |
11 | Assert.assertNotNull(creatorBrowser);
12 | Assert.assertEquals("aName", creatorBrowser.getName());
13 | Assert.assertEquals("aVersion", creatorBrowser.getVersion());
14 | Assert.assertEquals("my comment", creatorBrowser.getComment());
15 |
16 | creatorBrowser = map(UNKNOWN_PROPERTY, HarCreatorBrowser.class);
17 | Assert.assertNotNull(creatorBrowser);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/jackson/DefaultMapperFactory.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.jackson;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import com.fasterxml.jackson.databind.module.SimpleModule;
5 | import de.sstoehr.harreader.HarReaderMode;
6 |
7 | import java.util.Date;
8 |
9 | public class DefaultMapperFactory implements MapperFactory {
10 |
11 | public ObjectMapper instance(HarReaderMode mode) {
12 | ObjectMapper mapper = new ObjectMapper();
13 | SimpleModule module = new SimpleModule();
14 | if (mode == HarReaderMode.LAX) {
15 | module.addDeserializer(Date.class, new ExceptionIgnoringDateDeserializer());
16 | module.addDeserializer(Integer.class, new ExceptionIgnoringIntegerDeserializer());
17 | }
18 | mapper.registerModule(module);
19 | return mapper;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/jackson/ExceptionIgnoringIntegerDeserializer.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.jackson;
2 |
3 | import com.fasterxml.jackson.core.JsonParser;
4 | import com.fasterxml.jackson.databind.DeserializationContext;
5 | import com.fasterxml.jackson.databind.JsonDeserializer;
6 | import com.fasterxml.jackson.databind.deser.std.NumberDeserializers;
7 |
8 | import java.io.IOException;
9 |
10 | public class ExceptionIgnoringIntegerDeserializer extends JsonDeserializer {
11 | @Override
12 | public Integer deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
13 | try {
14 | NumberDeserializers.IntegerDeserializer integerDeserializer = new NumberDeserializers.IntegerDeserializer(Integer.class, null);
15 | return integerDeserializer.deserialize(jp, ctxt);
16 | } catch (IOException e) {
17 | //ignore
18 | }
19 | return null;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/jackson/ExceptionIgnoringDateDeserializer.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.jackson;
2 |
3 | import java.io.IOException;
4 | import java.util.Date;
5 |
6 | import com.fasterxml.jackson.core.JsonParser;
7 | import com.fasterxml.jackson.databind.DeserializationContext;
8 | import com.fasterxml.jackson.databind.JsonDeserializer;
9 | import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
10 |
11 | public class ExceptionIgnoringDateDeserializer extends JsonDeserializer {
12 |
13 | @Override
14 | public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws java.io.IOException {
15 | try {
16 | DateDeserializers.DateDeserializer dateDeserializer = new DateDeserializers.DateDeserializer();
17 | return dateDeserializer.deserialize(jp, ctxt);
18 | } catch (IOException e) {
19 | //ignore
20 | }
21 | return new Date(0L);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarPostDataParamTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | public class HarPostDataParamTest extends AbstractMapperTest {
6 |
7 | @Override
8 | public void testMapping() {
9 | HarPostDataParam postDataParam = map("{\"name\": \"aName\", \"value\": \"aValue\", \"fileName\": \"aFilename\", \"contentType\": \"aContentType\", \"comment\": \"My comment\"}", HarPostDataParam.class);
10 |
11 | Assert.assertEquals("aName", postDataParam.getName());
12 | Assert.assertEquals("aValue", postDataParam.getValue());
13 | Assert.assertEquals("aFilename", postDataParam.getFileName());
14 | Assert.assertEquals("aContentType", postDataParam.getContentType());
15 | Assert.assertEquals("My comment", postDataParam.getComment());
16 |
17 |
18 | postDataParam = map(UNKNOWN_PROPERTY, HarPostDataParam.class);
19 | Assert.assertNotNull(postDataParam);
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarContentTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | public class HarContentTest extends AbstractMapperTest {
6 |
7 | @Override
8 | public void testMapping() {
9 | HarContent content = map("{\"size\":123,\"compression\":45,\"mimeType\":\"mime/type\"," +
10 | "\"text\":\"my content\",\"encoding\":\"base64\",\"comment\":\"my comment\"}", HarContent.class);
11 |
12 | Assert.assertEquals(123L, (long) content.getSize());
13 | Assert.assertEquals(45L, (long) content.getCompression());
14 | Assert.assertEquals("mime/type", content.getMimeType());
15 | Assert.assertEquals("my content", content.getText());
16 | Assert.assertEquals("base64", content.getEncoding());
17 | Assert.assertEquals("my comment", content.getComment());
18 |
19 | content = map(UNKNOWN_PROPERTY, HarContent.class);
20 | Assert.assertNotNull(content);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Sebastian Stöhr
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/Har.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Main HTTP Archive Class.
10 | * @see speicification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class Har {
15 |
16 | private HarLog log;
17 |
18 | /**
19 | * @return HAR log.
20 | */
21 | public HarLog getLog() {
22 | if (log == null) {
23 | log = new HarLog();
24 | }
25 | return log;
26 | }
27 |
28 | public void setLog(HarLog log) {
29 | this.log = log;
30 | }
31 |
32 | @Override
33 | public boolean equals(Object o) {
34 | if (this == o) return true;
35 | if (o == null || getClass() != o.getClass()) return false;
36 | Har har = (Har) o;
37 | return Objects.equals(log, har.log);
38 | }
39 |
40 | @Override
41 | public int hashCode() {
42 | return Objects.hash(log);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarPostDataTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class HarPostDataTest extends AbstractMapperTest {
10 |
11 | private static final List EXPECTED_LIST = new ArrayList<>();
12 |
13 | @Override
14 | public void testMapping() {
15 | HarPostData postData = map("{\"mimeType\": \"aMimeType\", \"params\": [], \"text\":\"aText\", \"comment\": \"My comment\"}", HarPostData.class);
16 |
17 | Assert.assertEquals("aMimeType", postData.getMimeType());
18 | Assert.assertEquals(EXPECTED_LIST, postData.getParams());
19 | Assert.assertEquals("aText", postData.getText());
20 | Assert.assertEquals("My comment", postData.getComment());
21 |
22 | postData = map(UNKNOWN_PROPERTY, HarPostData.class);
23 | Assert.assertNotNull(postData);
24 | }
25 |
26 | @Test
27 | public void testParams() {
28 | HarPostData postData = new HarPostData();
29 | postData.setParams(null);
30 | Assert.assertNotNull(postData.getParams());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarCookieTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | import java.util.Date;
6 |
7 | public class HarCookieTest extends AbstractMapperTest {
8 |
9 | private final static Date EXPECTED_EXPIRES = new Date() {{
10 | setTime(1388577600000L);
11 | }};
12 |
13 | @Override
14 | public void testMapping() {
15 | HarCookie cookie = map("{\"name\":\"aName\",\"value\":\"aValue\",\"path\":\"/\",\"domain\":\"sstoehr.de\"," +
16 | "\"expires\":\"2014-01-01T12:00:00\",\"httpOnly\":\"true\",\"secure\":\"false\",\"comment\":\"my comment\"}", HarCookie.class);
17 |
18 | Assert.assertNotNull(cookie);
19 | Assert.assertEquals("aName", cookie.getName());
20 | Assert.assertEquals("aValue", cookie.getValue());
21 | Assert.assertEquals("/", cookie.getPath());
22 | Assert.assertEquals("sstoehr.de", cookie.getDomain());
23 | Assert.assertEquals(EXPECTED_EXPIRES, cookie.getExpires());
24 | Assert.assertEquals(true, cookie.getHttpOnly());
25 | Assert.assertEquals(false, cookie.getSecure());
26 | Assert.assertEquals("my comment", cookie.getComment());
27 |
28 | cookie = map(UNKNOWN_PROPERTY, HarCookie.class);
29 | Assert.assertNotNull(cookie);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarPageTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.util.Date;
7 |
8 | public class HarPageTest extends AbstractMapperTest {
9 |
10 | private final static Date EXPECTED_STARTED = new Date() {{
11 | setTime(1388577600000L);
12 | }};
13 |
14 | @Override
15 | public void testMapping() {
16 | HarPage page = map("{\"startedDateTime\":\"2014-01-01T12:00:00\",\"id\":\"anId\","
17 | + "\"title\":\"aTitle\",\"pageTimings\":{},\"comment\":\"my comment\", \"_add\": \"additional info\"}", HarPage.class);
18 |
19 | Assert.assertNotNull(page);
20 | Assert.assertEquals(EXPECTED_STARTED, page.getStartedDateTime());
21 | Assert.assertEquals("anId", page.getId());
22 | Assert.assertEquals("aTitle", page.getTitle());
23 | Assert.assertNotNull(page.getPageTimings());
24 | Assert.assertEquals("my comment", page.getComment());
25 | Assert.assertEquals("additional info", page.getAdditional().get("_add"));
26 |
27 | page = map(UNKNOWN_PROPERTY, HarPage.class);
28 | Assert.assertNotNull(page);
29 | }
30 |
31 | @Test
32 | public void testPageTimingsNull() {
33 | HarPage page = new HarPage();
34 | page.setPageTimings(null);
35 | Assert.assertNotNull(page.getPageTimings());
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarCacheTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 |
5 | import java.util.Date;
6 |
7 | public class HarCacheTest extends AbstractMapperTest {
8 |
9 | private final static Date EXPECTED_EXPIRES = new Date() {{
10 | setTime(1388577600000L);
11 | }};
12 | private final static Date EXPECTED_LAST_ACCESS = new Date() {{
13 | setTime(1370088000000L);
14 | }};
15 |
16 | @Override
17 | public void testMapping() {
18 | HarCache cache = map("{\"beforeRequest\":{\"expires\":\"2014-01-01T12:00:00\",\"lastAccess\":\"2013-06-01T12:00:00\",\"eTag\":\"abc123\"," +
19 | "\"hitCount\":3,\"comment\":\"my comment\"},\"afterRequest\":{},\"comment\":\"my comment 2\"}", HarCache.class);
20 |
21 | Assert.assertNotNull(cache.getBeforeRequest());
22 | Assert.assertEquals(EXPECTED_EXPIRES, cache.getBeforeRequest().getExpires());
23 | Assert.assertEquals(EXPECTED_LAST_ACCESS, cache.getBeforeRequest().getLastAccess());
24 | Assert.assertEquals("abc123", cache.getBeforeRequest().geteTag());
25 | Assert.assertEquals(3, (long) cache.getBeforeRequest().getHitCount());
26 | Assert.assertEquals("my comment", cache.getBeforeRequest().getComment());
27 |
28 | Assert.assertNotNull(cache.getAfterRequest());
29 |
30 | Assert.assertEquals("my comment 2", cache.getComment());
31 |
32 | cache = map(UNKNOWN_PROPERTY, HarCache.class);
33 | Assert.assertNotNull(cache);
34 |
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/HarReader.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import de.sstoehr.harreader.jackson.DefaultMapperFactory;
5 | import de.sstoehr.harreader.jackson.MapperFactory;
6 | import de.sstoehr.harreader.model.Har;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 |
11 | public class HarReader {
12 |
13 | private final MapperFactory mapperFactory;
14 |
15 | public HarReader(MapperFactory mapperFactory) {
16 | if (mapperFactory == null) {
17 | throw new IllegalArgumentException("mapperFactory must not be null!");
18 | }
19 | this.mapperFactory = mapperFactory;
20 | }
21 |
22 | public HarReader() {
23 | this(new DefaultMapperFactory());
24 | }
25 |
26 | public Har readFromFile(File har) throws HarReaderException {
27 | return this.readFromFile(har, HarReaderMode.STRICT);
28 | }
29 |
30 | public Har readFromFile(File har, HarReaderMode mode) throws HarReaderException {
31 | ObjectMapper mapper = mapperFactory.instance(mode);
32 | try {
33 | return mapper.readValue(har, Har.class);
34 | } catch (IOException e) {
35 | throw new HarReaderException(e);
36 | }
37 | }
38 |
39 | public Har readFromString(String har) throws HarReaderException {
40 | return this.readFromString(har, HarReaderMode.STRICT);
41 | }
42 |
43 | public Har readFromString(String har, HarReaderMode mode) throws HarReaderException {
44 | ObjectMapper mapper = mapperFactory.instance(mode);
45 | try {
46 | return mapper.readValue(har, Har.class);
47 | } catch (IOException e) {
48 | throw new HarReaderException(e);
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarPageTimingTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HarPageTimingTest extends AbstractMapperTest {
7 |
8 | private static final Integer EXPECTED_DEFAULT_DURATION = -1;
9 |
10 | @Test
11 | public void testOnContentLoad() {
12 | HarPageTiming pageTiming = new HarPageTiming();
13 | Assert.assertEquals(EXPECTED_DEFAULT_DURATION, pageTiming.getOnContentLoad());
14 |
15 | pageTiming.setOnContentLoad(1234);
16 | Assert.assertEquals(1234, (int) pageTiming.getOnContentLoad());
17 |
18 | pageTiming.setOnContentLoad(null);
19 | Assert.assertEquals(EXPECTED_DEFAULT_DURATION, pageTiming.getOnContentLoad());
20 | }
21 |
22 | @Test
23 | public void testOnLoad() {
24 | HarPageTiming pageTiming = new HarPageTiming();
25 | Assert.assertEquals(EXPECTED_DEFAULT_DURATION, pageTiming.getOnLoad());
26 |
27 | pageTiming.setOnLoad(1234);
28 | Assert.assertEquals(1234, (int) pageTiming.getOnLoad());
29 |
30 | pageTiming.setOnLoad(null);
31 | Assert.assertEquals(EXPECTED_DEFAULT_DURATION, pageTiming.getOnLoad());
32 | }
33 |
34 | @Override
35 | public void testMapping() {
36 | HarPageTiming pageTiming = map("{\"onContentLoad\": 1234, \"onLoad\": 5678, \"comment\": \"My comment\"}", HarPageTiming.class);
37 |
38 | Assert.assertEquals(1234, (int) pageTiming.getOnContentLoad());
39 | Assert.assertEquals(5678, (int) pageTiming.getOnLoad());
40 | Assert.assertEquals("My comment", pageTiming.getComment());
41 |
42 | pageTiming = map(UNKNOWN_PROPERTY, HarPageTiming.class);
43 | Assert.assertNotNull(pageTiming);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HttpStatus.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public enum HttpStatus {
7 |
8 | UNKNOWN_HTTP_STATUS(0),
9 |
10 | OK(200), CREATED(201), ACCEPTED(202), NO_CONTENT(204), RESET_CONTENT(205),
11 | PARTIAL_CONTENT(206),
12 |
13 | MOVED_PERMANENTLY(301), FOUND(302), SEE_OTHER(303), NOT_MODIFIED(304),
14 | USE_PROXY(305), TEMPORARY_REDIRECT(307),
15 |
16 | BAD_REQUEST(400), UNAUTHORIZED(401), PAYMENT_REQUIRED(402), FORBIDDEN(403),
17 | NOT_FOUND(404), METHOD_NOT_ALLOWED(405), NOT_ACCEPTABLE(406),
18 | PROXY_AUTHENTICATION_REQUIRED(407), REQUEST_TIMEOUT(408),
19 | CONFLICT(409), GONE(410), LENGTH_REQUIRED(411), PRECONDITION_FAILED(412),
20 | REQUEST_ENTITY_TOO_LARGE(413), REQUEST_URI_TOO_LONG(414),
21 | UNSUPPORTED_MEDIA_TYPE(415), REQUESTED_RANGE_NOT_SATISFIABLE(416),
22 | EXPECTATION_FAILED(417),
23 |
24 | INTERNAL_SERVER_ERROR(500), NOT_IMPLEMENTED(501),
25 | BAD_GATEWAY(502), SERVICE_UNAVAILABLE(503), GATEWAY_TIMEOUT(504),
26 | HTTP_VERSION_NOT_SUPPORTED(505);
27 |
28 | private static final Map CODE_MAP = new HashMap<>();
29 |
30 | static {
31 | for (HttpStatus status : HttpStatus.values()) {
32 | CODE_MAP.put(status.getCode(), status);
33 | }
34 | }
35 |
36 | private int code;
37 |
38 | private HttpStatus(int code) {
39 | this.code = code;
40 | }
41 |
42 | public int getCode() {
43 | return code;
44 | }
45 |
46 | public static HttpStatus byCode(int code) {
47 | HttpStatus status = CODE_MAP.get(code);
48 | if (status == null) {
49 | return UNKNOWN_HTTP_STATUS;
50 | }
51 | return status;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarTimingTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HarTimingTest extends AbstractMapperTest {
7 |
8 | @Override
9 | public void testMapping() {
10 | HarTiming timing = map("{\"blocked\": 3804,\"dns\": 23,\"connect\": 5,\"send\": 9,\"wait\": 5209,"
11 | + "\"receive\": 79, \"ssl\": 123, \"comment\": \"my comment\"}", HarTiming.class);
12 |
13 | Assert.assertNotNull(timing);
14 | Assert.assertEquals(3804, (int) timing.getBlocked());
15 | Assert.assertEquals(23, (int) timing.getDns());
16 | Assert.assertEquals(5, (int) timing.getConnect());
17 | Assert.assertEquals(9, (int) timing.getSend());
18 | Assert.assertEquals(5209, (int) timing.getWait());
19 | Assert.assertEquals(79, (int) timing.getReceive());
20 | Assert.assertEquals(123, (int) timing.getSsl());
21 | Assert.assertEquals("my comment", timing.getComment());
22 | }
23 |
24 | @Test
25 | public void testBlocked() {
26 | HarTiming timing = new HarTiming();
27 | timing.setBlocked(null);
28 | Assert.assertEquals(-1, (int) timing.getBlocked());
29 | }
30 |
31 | @Test
32 | public void testDns() {
33 | HarTiming timing = new HarTiming();
34 | timing.setDns(null);
35 | Assert.assertEquals(-1, (int) timing.getDns());
36 | }
37 |
38 | @Test
39 | public void testConnect() {
40 | HarTiming timing = new HarTiming();
41 | timing.setConnect(null);
42 | Assert.assertEquals(-1, (int) timing.getConnect());
43 | }
44 |
45 | @Test
46 | public void testSsl() {
47 | HarTiming timing = new HarTiming();
48 | timing.setSsl(null);
49 | Assert.assertEquals(-1, (int) timing.getSsl());
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarQueryParam.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about query params.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarQueryParam {
15 |
16 | private String name;
17 | private String value;
18 | private String comment;
19 |
20 | /**
21 | * @return Name of param, null if not present.
22 | */
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | /**
32 | * @return Value of param, null if not present.
33 | */
34 | public String getValue() {
35 | return value;
36 | }
37 |
38 | public void setValue(String value) {
39 | this.value = value;
40 | }
41 |
42 | /**
43 | * @return Comment provided by the user or application, null if not present.
44 | */
45 | public String getComment() {
46 | return comment;
47 | }
48 |
49 | public void setComment(String comment) {
50 | this.comment = comment;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object o) {
55 | if (this == o) return true;
56 | if (o == null || getClass() != o.getClass()) return false;
57 | HarQueryParam that = (HarQueryParam) o;
58 | return Objects.equals(name, that.name) &&
59 | Objects.equals(value, that.value) &&
60 | Objects.equals(comment, that.comment);
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | return Objects.hash(name, value, comment);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarHeader.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about a header used in request and/or response.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarHeader {
15 |
16 | private String name;
17 | private String value;
18 | private String comment;
19 |
20 | /**
21 | * @return Header name, null if not present.
22 | */
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | /**
32 | * @return Header value, null if not present.
33 | */
34 | public String getValue() {
35 | return value;
36 | }
37 |
38 | public void setValue(String value) {
39 | this.value = value;
40 | }
41 |
42 | /**
43 | * @return Comment provided by the user or application, null if not present.
44 | */
45 | public String getComment() {
46 | return comment;
47 | }
48 |
49 | public void setComment(String comment) {
50 | this.comment = comment;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object o) {
55 | if (this == o) return true;
56 | if (o == null || getClass() != o.getClass()) return false;
57 | HarHeader harHeader = (HarHeader) o;
58 | return Objects.equals(name, harHeader.name) &&
59 | Objects.equals(value, harHeader.value) &&
60 | Objects.equals(comment, harHeader.comment);
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | return Objects.hash(name, value, comment);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarCreatorBrowser.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about the application/browser used for creating HAR.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarCreatorBrowser {
15 |
16 | private String name;
17 | private String version;
18 | private String comment;
19 |
20 | /**
21 | * @return Name of the application/browser used for creating HAR, null if not present.
22 | */
23 | public String getName() {
24 | return name;
25 | }
26 |
27 | public void setName(String name) {
28 | this.name = name;
29 | }
30 |
31 | /**
32 | * @return Version of the application/browser used for creating HAR, null if not present.
33 | */
34 | public String getVersion() {
35 | return version;
36 | }
37 |
38 | public void setVersion(String version) {
39 | this.version = version;
40 | }
41 |
42 | /**
43 | * @return Comment provided by the user or application, null if not present.
44 | */
45 | public String getComment() {
46 | return comment;
47 | }
48 |
49 | public void setComment(String comment) {
50 | this.comment = comment;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object o) {
55 | if (this == o) return true;
56 | if (o == null || getClass() != o.getClass()) return false;
57 | HarCreatorBrowser that = (HarCreatorBrowser) o;
58 | return Objects.equals(name, that.name) &&
59 | Objects.equals(version, that.version) &&
60 | Objects.equals(comment, that.comment);
61 | }
62 |
63 | @Override
64 | public int hashCode() {
65 | return Objects.hash(name, version, comment);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarEntryTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.util.Date;
7 |
8 | public class HarEntryTest extends AbstractMapperTest {
9 |
10 | private final static Date EXPECTED_STARTED = new Date() {{
11 | setTime(1388577600000L);
12 | }};
13 |
14 | @Override
15 | public void testMapping() {
16 | HarEntry entry = map("{\"pageref\":\"aPageref\",\"startedDateTime\":\"2014-01-01T12:00:00\",\"time\":12345,"
17 | + "\"request\":{},\"response\":{},\"cache\":{},\"timings\":{},\"serverIPAddress\":\"1.2.3.4\",\"connection\":\"aConnection\","
18 | + "\"comment\":\"my comment\", \"_add\": \"additional info\"}", HarEntry.class);
19 |
20 | Assert.assertNotNull(entry);
21 | Assert.assertEquals("aPageref", entry.getPageref());
22 | Assert.assertEquals(EXPECTED_STARTED, entry.getStartedDateTime());
23 | Assert.assertEquals(12345, (int) entry.getTime());
24 | Assert.assertNotNull(entry.getRequest());
25 | Assert.assertNotNull(entry.getResponse());
26 | Assert.assertNotNull(entry.getCache());
27 | Assert.assertNotNull(entry.getTimings());
28 | Assert.assertEquals("1.2.3.4", entry.getServerIPAddress());
29 | Assert.assertEquals("aConnection", entry.getConnection());
30 | Assert.assertEquals("my comment", entry.getComment());
31 | Assert.assertEquals("additional info", entry.getAdditional().get("_add"));
32 |
33 | entry = map(UNKNOWN_PROPERTY, HarEntry.class);
34 | Assert.assertNotNull(entry);
35 | }
36 |
37 | @Test
38 | public void testRequestNull() {
39 | HarEntry entry = new HarEntry();
40 | entry.setRequest(null);
41 | Assert.assertNotNull(entry.getRequest());
42 | }
43 |
44 | @Test
45 | public void testResponseNull() {
46 | HarEntry entry = new HarEntry();
47 | entry.setResponse(null);
48 | Assert.assertNotNull(entry.getResponse());
49 | }
50 |
51 | @Test
52 | public void testCacheNull() {
53 | HarEntry entry = new HarEntry();
54 | entry.setCache(null);
55 | Assert.assertNotNull(entry.getCache());
56 | }
57 |
58 | @Test
59 | public void testTimingsNull() {
60 | HarEntry entry = new HarEntry();
61 | entry.setTimings(null);
62 | Assert.assertNotNull(entry.getTimings());
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarPageTiming.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about events occurring during page load.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarPageTiming {
15 |
16 | protected static final Integer DEFAULT_TIME = -1;
17 |
18 | private Integer onContentLoad = DEFAULT_TIME;
19 | private Integer onLoad = DEFAULT_TIME;
20 | private String comment;
21 |
22 | /**
23 | * @return Duration in ms until content is loaded.
24 | * {@link #DEFAULT_TIME} when no information available.
25 | */
26 | public Integer getOnContentLoad() {
27 | if (onContentLoad == null) {
28 | return DEFAULT_TIME;
29 | }
30 | return onContentLoad;
31 | }
32 |
33 | public void setOnContentLoad(Integer onContentLoad) {
34 | this.onContentLoad = onContentLoad;
35 | }
36 |
37 | /**
38 | * @return Duration in ms until onLoad event is fired.
39 | * {@link #DEFAULT_TIME} when no information available.
40 | */
41 | public Integer getOnLoad() {
42 | if (onLoad == null) {
43 | return DEFAULT_TIME;
44 | }
45 | return onLoad;
46 | }
47 |
48 | public void setOnLoad(Integer onLoad) {
49 | this.onLoad = onLoad;
50 | }
51 |
52 | /**
53 | * @return Comment provided by the user or application, null if not present.
54 | */
55 | public String getComment() {
56 | return comment;
57 | }
58 |
59 | public void setComment(String comment) {
60 | this.comment = comment;
61 | }
62 |
63 | @Override
64 | public boolean equals(Object o) {
65 | if (this == o) return true;
66 | if (o == null || getClass() != o.getClass()) return false;
67 | HarPageTiming that = (HarPageTiming) o;
68 | return Objects.equals(onContentLoad, that.onContentLoad) &&
69 | Objects.equals(onLoad, that.onLoad) &&
70 | Objects.equals(comment, that.comment);
71 | }
72 |
73 | @Override
74 | public int hashCode() {
75 | return Objects.hash(onContentLoad, onLoad, comment);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarPostData.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.Objects;
9 |
10 | /**
11 | * Information about POST data.
12 | * @see specification
13 | */
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | @JsonIgnoreProperties(ignoreUnknown = true)
16 | public class HarPostData {
17 |
18 | private String mimeType;
19 | private List params = new ArrayList<>();
20 | private String text;
21 | private String comment;
22 |
23 | /**
24 | * @return MIME type of posted data, null if not present.
25 | */
26 | public String getMimeType() {
27 | return mimeType;
28 | }
29 |
30 | public void setMimeType(String mimeType) {
31 | this.mimeType = mimeType;
32 | }
33 |
34 | /**
35 | * @return List of posted params.
36 | */
37 | public List getParams() {
38 | if (params == null) {
39 | params = new ArrayList<>();
40 | }
41 | return params;
42 | }
43 |
44 | public void setParams(List params) {
45 | this.params = params;
46 | }
47 |
48 | /**
49 | * @return Plain text posted data, null if not present.
50 | */
51 | public String getText() {
52 | return text;
53 | }
54 |
55 | public void setText(String text) {
56 | this.text = text;
57 | }
58 |
59 | /**
60 | * @return Comment provided by the user or application, null if not present.
61 | */
62 | public String getComment() {
63 | return comment;
64 | }
65 |
66 | public void setComment(String comment) {
67 | this.comment = comment;
68 | }
69 |
70 | @Override
71 | public boolean equals(Object o) {
72 | if (this == o) return true;
73 | if (o == null || getClass() != o.getClass()) return false;
74 | HarPostData that = (HarPostData) o;
75 | return Objects.equals(mimeType, that.mimeType) &&
76 | Objects.equals(params, that.params) &&
77 | Objects.equals(text, that.text) &&
78 | Objects.equals(comment, that.comment);
79 | }
80 |
81 | @Override
82 | public int hashCode() {
83 | return Objects.hash(mimeType, params, text, comment);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/HarReaderTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader;
2 |
3 | import de.sstoehr.harreader.model.Har;
4 | import org.junit.Assert;
5 | import org.junit.Test;
6 |
7 | import java.io.File;
8 |
9 | public class HarReaderTest {
10 |
11 | private HarReader harReader = new HarReader();
12 |
13 | @Test
14 | public void test() throws HarReaderException {
15 | File harFile = new File("src/test/resources/sstoehr.har");
16 | Har har = harReader.readFromFile(harFile);
17 | Assert.assertNotNull(har);
18 | }
19 |
20 | @Test
21 | public void missingLog() throws HarReaderException {
22 | Har har = harReader.readFromString("{\"unknown\":\"!\"}");
23 | Assert.assertNotNull(har);
24 | }
25 |
26 | @Test(expected = HarReaderException.class)
27 | public void invalidDateStrict() throws HarReaderException {
28 | File harFile = new File("src/test/resources/sstoehr.invalid-date.har");
29 | harReader.readFromFile(harFile);
30 | }
31 |
32 | @Test
33 | public void invalidDateLax() throws HarReaderException {
34 | File harFile = new File("src/test/resources/sstoehr.invalid-date.har");
35 | Har har = harReader.readFromFile(harFile, HarReaderMode.LAX);
36 | Assert.assertNotNull(har);
37 | }
38 |
39 | @Test(expected = HarReaderException.class)
40 | public void invalidIntegerStrict() throws HarReaderException {
41 | File harFile = new File("src/test/resources/sstoehr.invalid-integer.har");
42 | harReader.readFromFile(harFile);
43 | }
44 |
45 | @Test
46 | public void invalidIntegerLax() throws HarReaderException {
47 | File harFile = new File("src/test/resources/sstoehr.invalid-integer.har");
48 | Har har = harReader.readFromFile(harFile, HarReaderMode.LAX);
49 | Assert.assertNotNull(har);
50 | }
51 |
52 | @Test(expected = IllegalArgumentException.class)
53 | public void mapperFactoryNotNull() {
54 | new HarReader(null);
55 | }
56 |
57 | @Test
58 | public void testEquals() throws HarReaderException {
59 | File harFile = new File("src/test/resources/sstoehr.har");
60 | Har har1 = harReader.readFromFile(harFile);
61 | Har har2 = harReader.readFromFile(harFile);
62 | Assert.assertTrue(har1.equals(har2));
63 | }
64 |
65 | @Test
66 | public void testHashCode() throws HarReaderException {
67 | File harFile = new File("src/test/resources/sstoehr.har");
68 | Har har1 = harReader.readFromFile(harFile);
69 | Har har2 = harReader.readFromFile(harFile);
70 | Assert.assertEquals(har1.hashCode(), har2.hashCode());
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarResponseTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HarResponseTest extends AbstractMapperTest {
7 |
8 | @Override
9 | public void testMapping() {
10 | HarResponse response = map("{\"status\": 200,\"statusText\": \"OK\",\"httpVersion\": \"HTTP/1.1\","
11 | + "\"cookies\": [],\"headers\": [],\"content\": {},\"redirectURL\": \"redirectUrl\",\"headersSize\": 318,"
12 | + "\"bodySize\": 16997,\"comment\": \"My comment\", \"_add\": \"additional info\"}", HarResponse.class);
13 |
14 | Assert.assertNotNull(response);
15 | Assert.assertEquals(200, response.getStatus());
16 | Assert.assertEquals("OK", response.getStatusText());
17 | Assert.assertEquals("HTTP/1.1", response.getHttpVersion());
18 | Assert.assertNotNull(response.getCookies());
19 | Assert.assertNotNull(response.getHeaders());
20 | Assert.assertNotNull(response.getContent());
21 | Assert.assertEquals("redirectUrl", response.getRedirectURL());
22 | Assert.assertEquals(318L, (long) response.getHeadersSize());
23 | Assert.assertEquals(16997L, (long) response.getBodySize());
24 | Assert.assertEquals("My comment", response.getComment());
25 | Assert.assertEquals("additional info", response.getAdditional().get("_add"));
26 | }
27 |
28 | @Test
29 | public void testStatus() {
30 | HarResponse response = new HarResponse();
31 | Assert.assertEquals(0, response.getStatus());
32 | }
33 |
34 | @Test
35 | public void testCookies() {
36 | HarResponse response = new HarResponse();
37 | response.setCookies(null);
38 | Assert.assertNotNull(response.getCookies());
39 | }
40 |
41 | @Test
42 | public void testHeaders() {
43 | HarResponse response = new HarResponse();
44 | response.setHeaders(null);
45 | Assert.assertNotNull(response.getHeaders());
46 | }
47 |
48 | @Test
49 | public void testContent() {
50 | HarResponse response = new HarResponse();
51 | response.setContent(null);
52 | Assert.assertNotNull(response.getContent());
53 | }
54 |
55 | @Test
56 | public void testHeadersSize() {
57 | HarResponse response = new HarResponse();
58 | response.setHeadersSize(null);
59 | Assert.assertEquals(-1L, (long) response.getHeadersSize());
60 | }
61 |
62 | @Test
63 | public void testBodySize() {
64 | HarResponse response = new HarResponse();
65 | response.setBodySize(null);
66 | Assert.assertEquals(-1L, (long) response.getBodySize());
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarPostDataParam.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about POST params.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarPostDataParam {
15 |
16 | private String name;
17 | private String value;
18 | private String fileName;
19 | private String contentType;
20 | private String comment;
21 |
22 | /**
23 | * @return Name of param, null if not present.
24 | */
25 | public String getName() {
26 | return name;
27 | }
28 |
29 | public void setName(String name) {
30 | this.name = name;
31 | }
32 |
33 | /**
34 | * @return Value of a param or content of posted file, null if not present.
35 | */
36 | public String getValue() {
37 | return value;
38 | }
39 |
40 | public void setValue(String value) {
41 | this.value = value;
42 | }
43 |
44 | /**
45 | * @return Name of posted file, null if not present.
46 | */
47 | public String getFileName() {
48 | return fileName;
49 | }
50 |
51 | public void setFileName(String fileName) {
52 | this.fileName = fileName;
53 | }
54 |
55 | /**
56 | * @return Content type of posted file, null if not present.
57 | */
58 | public String getContentType() {
59 | return contentType;
60 | }
61 |
62 | public void setContentType(String contentType) {
63 | this.contentType = contentType;
64 | }
65 |
66 | /**
67 | * @return Comment provided by the user or application, null if not present.
68 | */
69 | public String getComment() {
70 | return comment;
71 | }
72 |
73 | public void setComment(String comment) {
74 | this.comment = comment;
75 | }
76 |
77 | @Override
78 | public boolean equals(Object o) {
79 | if (this == o) return true;
80 | if (o == null || getClass() != o.getClass()) return false;
81 | HarPostDataParam that = (HarPostDataParam) o;
82 | return Objects.equals(name, that.name) &&
83 | Objects.equals(value, that.value) &&
84 | Objects.equals(fileName, that.fileName) &&
85 | Objects.equals(contentType, that.contentType) &&
86 | Objects.equals(comment, that.comment);
87 | }
88 |
89 | @Override
90 | public int hashCode() {
91 | return Objects.hash(name, value, fileName, contentType, comment);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarLogTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 |
9 | public class HarLogTest extends AbstractMapperTest {
10 |
11 | private static final String EXPECTED_DEFAULT_VERSION = "1.1";
12 | private static final List EXPECTED_PAGES_LIST = new ArrayList<>();
13 | private static final List EXPECTED_ENTRIES_LIST = new ArrayList<>();
14 |
15 | @Test
16 | public void testVersion() {
17 | HarLog log = new HarLog();
18 | Assert.assertEquals(EXPECTED_DEFAULT_VERSION, log.getVersion());
19 |
20 | log.setVersion("1.2");
21 | Assert.assertEquals("1.2", log.getVersion());
22 |
23 | log.setVersion(null);
24 | Assert.assertEquals(EXPECTED_DEFAULT_VERSION, log.getVersion());
25 |
26 | log.setVersion("");
27 | Assert.assertEquals(EXPECTED_DEFAULT_VERSION, log.getVersion());
28 |
29 | log.setVersion(" ");
30 | Assert.assertEquals(EXPECTED_DEFAULT_VERSION, log.getVersion());
31 | }
32 |
33 | @Test
34 | public void testPages() {
35 | HarLog log = new HarLog();
36 | Assert.assertEquals(EXPECTED_PAGES_LIST, log.getPages());
37 |
38 | log.setPages(null);
39 | Assert.assertEquals(EXPECTED_PAGES_LIST, log.getPages());
40 | }
41 |
42 | @Test
43 | public void testEntries() {
44 | HarLog log = new HarLog();
45 | Assert.assertEquals(EXPECTED_ENTRIES_LIST, log.getEntries());
46 |
47 | log.setEntries(null);
48 | Assert.assertEquals(EXPECTED_ENTRIES_LIST, log.getEntries());
49 | }
50 |
51 | @Test
52 | public void testCreatorNull() {
53 | HarLog log = new HarLog();
54 | log.setCreator(null);
55 | Assert.assertNotNull(log.getCreator());
56 | }
57 |
58 | @Test
59 | public void testBrowserNull() {
60 | HarLog log = new HarLog();
61 | log.setBrowser(null);
62 | Assert.assertNotNull(log.getBrowser());
63 | }
64 |
65 | @Override
66 | public void testMapping() {
67 | HarLog log = map("{\"creator\": {}, \"browser\": {}, \"comment\": \"My comment\"}", HarLog.class);
68 |
69 | Assert.assertEquals(EXPECTED_DEFAULT_VERSION, log.getVersion());
70 | Assert.assertNotNull(log.getCreator());
71 | Assert.assertNotNull(log.getBrowser());
72 | Assert.assertEquals(EXPECTED_PAGES_LIST, log.getPages());
73 | Assert.assertEquals(EXPECTED_ENTRIES_LIST, log.getEntries());
74 | Assert.assertEquals("My comment", log.getComment());
75 |
76 | log = map(UNKNOWN_PROPERTY, HarLog.class);
77 | Assert.assertNotNull(log);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/test/java/de/sstoehr/harreader/model/HarRequestTest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import org.junit.Assert;
4 | import org.junit.Test;
5 |
6 | public class HarRequestTest extends AbstractMapperTest {
7 |
8 | @Override
9 | public void testMapping() {
10 | HarRequest request = map("{\"method\": \"GET\",\"url\": "
11 | + "\"http://www.sebastianstoehr.de/\",\"httpVersion\": "
12 | + "\"HTTP/1.1\",\"cookies\": [],\"headers\": [],\"queryString\": [],"
13 | + "\"headersSize\": 676,\"bodySize\": -1, \"postData\": {}, \"comment\":\"my comment\","
14 | + "\"_add\": \"additional info\"}", HarRequest.class);
15 |
16 | Assert.assertNotNull(request);
17 | Assert.assertEquals(HttpMethod.GET, request.getMethod());
18 | Assert.assertEquals("http://www.sebastianstoehr.de/", request.getUrl());
19 | Assert.assertEquals("HTTP/1.1", request.getHttpVersion());
20 | Assert.assertNotNull(request.getCookies());
21 | Assert.assertNotNull(request.getHeaders());
22 | Assert.assertNotNull(request.getQueryString());
23 | Assert.assertNotNull(request.getPostData());
24 | Assert.assertEquals(676L, (long) request.getHeadersSize());
25 | Assert.assertEquals(-1L, (long) request.getBodySize());
26 | Assert.assertEquals("my comment", request.getComment());
27 | Assert.assertEquals("additional info", request.getAdditional().get("_add"));
28 | }
29 |
30 | @Test
31 | public void testCookies() {
32 | HarRequest request = new HarRequest();
33 | request.setCookies(null);
34 | Assert.assertNotNull(request.getCookies());
35 | }
36 |
37 | @Test
38 | public void testHeaders() {
39 | HarRequest request = new HarRequest();
40 | request.setHeaders(null);
41 | Assert.assertNotNull(request.getHeaders());
42 | }
43 |
44 | @Test
45 | public void testQueryString() {
46 | HarRequest request = new HarRequest();
47 | request.setQueryString(null);
48 | Assert.assertNotNull(request.getQueryString());
49 | }
50 |
51 | @Test
52 | public void testPostData() {
53 | HarRequest request = new HarRequest();
54 | request.setPostData(null);
55 | Assert.assertNotNull(request.getPostData());
56 | }
57 |
58 | @Test
59 | public void testHeadersSize() {
60 | HarRequest request = new HarRequest();
61 | request.setHeadersSize(null);
62 | Assert.assertEquals(-1L, (long) request.getHeadersSize());
63 | }
64 |
65 | @Test
66 | public void testBodySize() {
67 | HarRequest request = new HarRequest();
68 | request.setBodySize(null);
69 | Assert.assertEquals(-1L, (long) request.getBodySize());
70 | }
71 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | HAR reader
2 | ==========
3 |
4 | Read [HTTP Archives](http://www.softwareishard.com/blog/har-12-spec/) with Java.
5 |
6 | ```
7 |
8 | de.sstoehr
9 | har-reader
10 | 2.1.0
11 |
12 | ```
13 |
14 | [](https://travis-ci.org/sdstoehr/har-reader)
15 | [](https://coveralls.io/r/sdstoehr/har-reader?branch=master)
16 | [](http://mvnrepository.com/artifact/de.sstoehr/har-reader)
17 |
18 | ## Usage
19 |
20 | Reading HAR from File:
21 |
22 | ```java
23 | HarReader harReader = new HarReader();
24 | Har har = harReader.readFromFile(new File("myhar.har"));
25 | System.out.println(har.getLog().getCreator().getName());
26 | ```
27 |
28 | Reading HAR from String:
29 |
30 | ```java
31 | HarReader harReader = new HarReader();
32 | Har har = harReader.readFromString("{ ... HAR-JSON-Data ... }");
33 | ```
34 |
35 | ### Customizing HAR reader
36 |
37 | As of version 2.0.0 you can create your own `MapperFactory` [(DefaultMapperFactory)](src/main/java/de/sstoehr/harreader/jackson/DefaultMapperFactory.java)
38 |
39 |
40 | ```java
41 | public class MyMapperFactory implements MapperFactory {
42 | public ObjectMapper instance(HarReaderMode mode) {
43 | ObjectMapper mapper = new ObjectMapper();
44 | SimpleModule module = new SimpleModule();
45 |
46 | // configure Jackson object mapper as needed
47 |
48 | mapper.registerModule(module);
49 | return mapper;
50 | }
51 | }
52 | ```
53 |
54 | You can now use your configuration by instantiating the `HarReader` with your `MapperFactory`:
55 |
56 | ```java
57 | HarReader harReader = new HarReader(new MyMapperFactory());
58 | ```
59 |
60 | ## Latest Releases
61 |
62 | ### 2.1.0 - 2018-03-11
63 |
64 | * You can now access additional fields, which are not part of the HAR spec:
65 |
66 | ```java
67 | response.getAdditional().get("_transferSize");
68 | ```
69 |
70 | [Details](https://github.com/sdstoehr/har-reader/releases/tag/har-reader-2.1.0)
71 |
72 | ### 2.0.3 - 2017-04-14
73 |
74 | * Added equals and hashCode methods
75 |
76 | ### 2.0.2 - 2016-11-21
77 |
78 | * Added CCM_POST HttpMethod to enum
79 |
80 | ### 2.0.1 - 2016-04-16
81 |
82 | * Ignore invalid integers in lax mode
83 |
84 | [Details](https://github.com/sdstoehr/har-reader/releases/tag/har-reader-2.0.1)
85 |
86 | ### 2.0.0 - 2015-08-30
87 |
88 | * HAR reader is now easier customizable. Use your own `MapperFactory` to adjust HAR reader for your project!
89 | * HAR reader threw exceptions, when required fields were empty. This behaviour was changed, so that you can now read non-standard-compliant HAR files
90 |
91 | [Details](https://github.com/sdstoehr/har-reader/releases/tag/har-reader-2.0.0)
92 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarContent.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | /**
9 | * Information about the response's content.
10 | * @see specification
11 | */
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class HarContent {
15 |
16 | private Long size;
17 | private Long compression;
18 | private String mimeType;
19 | private String text;
20 | private String encoding;
21 | private String comment;
22 |
23 | /**
24 | * @return Length of returned content in bytes, null if not present.
25 | */
26 | public Long getSize() {
27 | return size;
28 | }
29 |
30 | public void setSize(Long size) {
31 | this.size = size;
32 | }
33 |
34 | /**
35 | * @return Number of bytes saved by compression, null if not present.
36 | */
37 | public Long getCompression() {
38 | return compression;
39 | }
40 |
41 | public void setCompression(Long compression) {
42 | this.compression = compression;
43 | }
44 |
45 | /**
46 | * @return MIME-Type of response, null if not present. May include the charset.
47 | */
48 | public String getMimeType() {
49 | return mimeType;
50 | }
51 |
52 | public void setMimeType(String mimeType) {
53 | this.mimeType = mimeType;
54 | }
55 |
56 | /**
57 | * @return Response body loaded from server or cache, null if not present.
58 | * Binary content may be encoded using encoding specified by {@link #getEncoding()}.
59 | */
60 | public String getText() {
61 | return text;
62 | }
63 |
64 | public void setText(String text) {
65 | this.text = text;
66 | }
67 |
68 | /**
69 | * @return Encoding used for encoding response body, null if not present.
70 | * @see #getText()
71 | */
72 | public String getEncoding() {
73 | return encoding;
74 | }
75 |
76 | public void setEncoding(String encoding) {
77 | this.encoding = encoding;
78 | }
79 |
80 | /**
81 | * @return Comment provided by the user or application, null if not present.
82 | */
83 | public String getComment() {
84 | return comment;
85 | }
86 |
87 | public void setComment(String comment) {
88 | this.comment = comment;
89 | }
90 |
91 | @Override
92 | public boolean equals(Object o) {
93 | if (this == o) return true;
94 | if (o == null || getClass() != o.getClass()) return false;
95 | HarContent that = (HarContent) o;
96 | return Objects.equals(size, that.size) &&
97 | Objects.equals(compression, that.compression) &&
98 | Objects.equals(mimeType, that.mimeType) &&
99 | Objects.equals(text, that.text) &&
100 | Objects.equals(encoding, that.encoding) &&
101 | Objects.equals(comment, that.comment);
102 | }
103 |
104 | @Override
105 | public int hashCode() {
106 | return Objects.hash(size, compression, mimeType, text, encoding, comment);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarPage.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonAnyGetter;
4 | import com.fasterxml.jackson.annotation.JsonAnySetter;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
7 | import com.fasterxml.jackson.annotation.JsonInclude;
8 |
9 | import java.util.Date;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Information about an exported page.
16 | * @see specification
17 | */
18 | @JsonInclude(JsonInclude.Include.NON_NULL)
19 | @JsonIgnoreProperties(ignoreUnknown = true)
20 | public class HarPage {
21 |
22 | private Date startedDateTime;
23 | private String id;
24 | private String title;
25 | private HarPageTiming pageTimings;
26 | private String comment;
27 | private Map additional = new HashMap<>();
28 |
29 | /**
30 | * @return Start time of page load, null if not present.
31 | */
32 | @JsonFormat(shape = JsonFormat.Shape.STRING)
33 | public Date getStartedDateTime() {
34 | return startedDateTime;
35 | }
36 |
37 | public void setStartedDateTime(Date startedDateTime) {
38 | this.startedDateTime = startedDateTime;
39 | }
40 |
41 | /**
42 | * @return Unique identifier, null if not present.
43 | */
44 | public String getId() {
45 | return id;
46 | }
47 |
48 | public void setId(String id) {
49 | this.id = id;
50 | }
51 |
52 | /**
53 | * @return Page title, null if not present.
54 | */
55 | public String getTitle() {
56 | return title;
57 | }
58 |
59 | public void setTitle(String title) {
60 | this.title = title;
61 | }
62 |
63 | /**
64 | * @return Detailed information about page loading timings.
65 | */
66 | public HarPageTiming getPageTimings() {
67 | if (pageTimings == null) {
68 | pageTimings = new HarPageTiming();
69 | }
70 | return pageTimings;
71 | }
72 |
73 | public void setPageTimings(HarPageTiming pageTimings) {
74 | this.pageTimings = pageTimings;
75 | }
76 |
77 | /**
78 | * @return Comment provided by the user or application, null if not present.
79 | */
80 | public String getComment() {
81 | return comment;
82 | }
83 |
84 | public void setComment(String comment) {
85 | this.comment = comment;
86 | }
87 |
88 | @JsonAnyGetter
89 | public Map getAdditional() {
90 | return additional;
91 | }
92 |
93 | @JsonAnySetter
94 | public void setAdditionalField(String name, Object value) {
95 | this.additional.put(name, value);
96 | }
97 |
98 | @Override
99 | public boolean equals(Object o) {
100 | if (this == o) return true;
101 | if (o == null || getClass() != o.getClass()) return false;
102 | HarPage harPage = (HarPage) o;
103 | return Objects.equals(startedDateTime, harPage.startedDateTime) &&
104 | Objects.equals(id, harPage.id) &&
105 | Objects.equals(title, harPage.title) &&
106 | Objects.equals(pageTimings, harPage.pageTimings) &&
107 | Objects.equals(comment, harPage.comment) &&
108 | Objects.equals(additional, harPage.additional);
109 | }
110 |
111 | @Override
112 | public int hashCode() {
113 | return Objects.hash(startedDateTime, id, title, pageTimings, comment, additional);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarLog.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.Objects;
9 |
10 | /**
11 | * Root object of exported data.
12 | * @see specification
13 | */
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | @JsonIgnoreProperties(ignoreUnknown = true)
16 | public class HarLog {
17 |
18 | protected static final String DEFAULT_VERSION = "1.1";
19 |
20 | private String version = DEFAULT_VERSION;
21 | private HarCreatorBrowser creator;
22 | private HarCreatorBrowser browser;
23 | private List pages = new ArrayList<>();
24 | private List entries = new ArrayList<>();
25 | private String comment;
26 |
27 | /**
28 | * @return Version number of the format.
29 | * Defaults to {@link #DEFAULT_VERSION}
30 | */
31 | public String getVersion() {
32 | return version;
33 | }
34 |
35 | public void setVersion(String version) {
36 | if (version == null || version.trim().equals("")) {
37 | version = DEFAULT_VERSION;
38 | }
39 | this.version = version;
40 | }
41 |
42 | /**
43 | * @return Information about the application used to generate HAR.
44 | */
45 | public HarCreatorBrowser getCreator() {
46 | if (creator == null) {
47 | creator = new HarCreatorBrowser();
48 | }
49 | return creator;
50 | }
51 |
52 | public void setCreator(HarCreatorBrowser creator) {
53 | this.creator = creator;
54 | }
55 |
56 | /**
57 | * @return Information about the browser used.
58 | */
59 | public HarCreatorBrowser getBrowser() {
60 | if (browser == null) {
61 | browser = new HarCreatorBrowser();
62 | }
63 | return browser;
64 | }
65 |
66 | public void setBrowser(HarCreatorBrowser browser) {
67 | this.browser = browser;
68 | }
69 |
70 | /**
71 | * @return List of all exported pages, may be empty.
72 | */
73 | public List getPages() {
74 | if (pages == null) {
75 | pages = new ArrayList<>();
76 | }
77 | return pages;
78 | }
79 |
80 | public void setPages(List pages) {
81 | this.pages = pages;
82 | }
83 |
84 | /**
85 | * @return List of all exported requests, may be empty.
86 | */
87 | public List getEntries() {
88 | if (entries == null) {
89 | entries = new ArrayList<>();
90 | }
91 | return entries;
92 | }
93 |
94 | public void setEntries(List entries) {
95 | this.entries = entries;
96 | }
97 |
98 | /**
99 | * @return Comment provided by the user or application, null if not present.
100 | */
101 | public String getComment() {
102 | return comment;
103 | }
104 |
105 | public void setComment(String comment) {
106 | this.comment = comment;
107 | }
108 |
109 | @Override
110 | public boolean equals(Object o) {
111 | if (this == o) return true;
112 | if (o == null || getClass() != o.getClass()) return false;
113 | HarLog harLog = (HarLog) o;
114 | return Objects.equals(version, harLog.version) &&
115 | Objects.equals(creator, harLog.creator) &&
116 | Objects.equals(browser, harLog.browser) &&
117 | Objects.equals(pages, harLog.pages) &&
118 | Objects.equals(entries, harLog.entries) &&
119 | Objects.equals(comment, harLog.comment);
120 | }
121 |
122 | @Override
123 | public int hashCode() {
124 | return Objects.hash(version, creator, browser, pages, entries, comment);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | org.sonatype.oss
7 | oss-parent
8 | 7
9 |
10 |
11 | de.sstoehr
12 | har-reader
13 | 2.1.1-SNAPSHOT
14 | jar
15 |
16 | har-reader
17 | A library to access HTTP archive format with Java
18 | https://github.com/sdstoehr/har-reader
19 |
20 |
21 | UTF-8
22 | 2.9.4
23 |
24 |
25 |
26 |
27 | com.fasterxml.jackson.core
28 | jackson-core
29 | ${jackson.version}
30 |
31 |
32 |
33 | com.fasterxml.jackson.core
34 | jackson-databind
35 | ${jackson.version}
36 |
37 |
38 |
39 | junit
40 | junit
41 | 4.12
42 | test
43 |
44 |
45 |
46 |
47 |
48 |
49 | maven-compiler-plugin
50 | 3.1
51 |
52 | 1.7
53 | 1.7
54 |
55 |
56 |
57 | maven-failsafe-plugin
58 | 2.6
59 |
60 |
61 |
62 | integration-test
63 | verify
64 |
65 |
66 |
67 |
68 |
69 | org.eluder.coveralls
70 | coveralls-maven-plugin
71 | 4.3.0
72 |
73 |
74 | org.codehaus.mojo
75 | cobertura-maven-plugin
76 | 2.7
77 |
78 | xml
79 | 256m
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | sdstoehr
88 | Sebastian Stöhr
89 | sebastian@sebastianstoehr.de
90 |
91 |
92 |
93 |
94 |
95 | The MIT License
96 | http://www.opensource.org/licenses/mit-license.php
97 | repo
98 |
99 |
100 |
101 |
102 | https://github.com/sdstoehr/har-reader.git
103 | scm:git:git@github.com:sdstoehr/har-reader.git
104 | scm:git:git@github.com:sdstoehr/har-reader.git
105 |
106 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarCookie.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonFormat;
4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 |
7 | import java.util.Date;
8 | import java.util.Objects;
9 |
10 | /**
11 | * Information about a cookie used in request and/or response.
12 | * @see specification
13 | */
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | @JsonIgnoreProperties(ignoreUnknown = true)
16 | public class HarCookie {
17 |
18 | private String name;
19 | private String value;
20 | private String path;
21 | private String domain;
22 | private Date expires;
23 | private Boolean httpOnly;
24 | private Boolean secure;
25 | private String comment;
26 |
27 | /**
28 | * @return Name of the cookie, null if not present.
29 | */
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public void setName(String name) {
35 | this.name = name;
36 | }
37 |
38 | /**
39 | * @return Value of the cookie, null if not present.
40 | */
41 | public String getValue() {
42 | return value;
43 | }
44 |
45 | public void setValue(String value) {
46 | this.value = value;
47 | }
48 |
49 | /**
50 | * @return The cookie's path, null if not present.
51 | */
52 | public String getPath() {
53 | return path;
54 | }
55 |
56 | public void setPath(String path) {
57 | this.path = path;
58 | }
59 |
60 | /**
61 | * @return The cookie's domain, null if not present.
62 | */
63 | public String getDomain() {
64 | return domain;
65 | }
66 |
67 | public void setDomain(String domain) {
68 | this.domain = domain;
69 | }
70 |
71 | /**
72 | * @return The cookie's expiration time, null if not present.
73 | */
74 | @JsonFormat(shape = JsonFormat.Shape.STRING)
75 | public Date getExpires() {
76 | return expires;
77 | }
78 |
79 | public void setExpires(Date expires) {
80 | this.expires = expires;
81 | }
82 |
83 | /**
84 | * @return Whether the cookie is HTTP only, null if not present.
85 | */
86 | public Boolean getHttpOnly() {
87 | return httpOnly;
88 | }
89 |
90 | public void setHttpOnly(Boolean httpOnly) {
91 | this.httpOnly = httpOnly;
92 | }
93 |
94 | /**
95 | * @return Whether the cookie was transmitted via SSL, null if not present.
96 | */
97 | public Boolean getSecure() {
98 | return secure;
99 | }
100 |
101 | public void setSecure(Boolean secure) {
102 | this.secure = secure;
103 | }
104 |
105 | /**
106 | * @return Comment provided by the user or application, null if not present.
107 | */
108 | public String getComment() {
109 | return comment;
110 | }
111 |
112 | public void setComment(String comment) {
113 | this.comment = comment;
114 | }
115 |
116 | @Override
117 | public boolean equals(Object o) {
118 | if (this == o) return true;
119 | if (o == null || getClass() != o.getClass()) return false;
120 | HarCookie harCookie = (HarCookie) o;
121 | return Objects.equals(name, harCookie.name) &&
122 | Objects.equals(value, harCookie.value) &&
123 | Objects.equals(path, harCookie.path) &&
124 | Objects.equals(domain, harCookie.domain) &&
125 | Objects.equals(expires, harCookie.expires) &&
126 | Objects.equals(httpOnly, harCookie.httpOnly) &&
127 | Objects.equals(secure, harCookie.secure) &&
128 | Objects.equals(comment, harCookie.comment);
129 | }
130 |
131 | @Override
132 | public int hashCode() {
133 | return Objects.hash(name, value, path, domain, expires, httpOnly, secure, comment);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarTiming.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.fasterxml.jackson.annotation.JsonInclude;
5 |
6 | import java.util.Objects;
7 |
8 | @JsonInclude(JsonInclude.Include.NON_NULL)
9 | @JsonIgnoreProperties(ignoreUnknown = true)
10 | public class HarTiming {
11 |
12 | protected static final Integer DEFAULT_TIME = -1;
13 |
14 | private Integer blocked;
15 | private Integer dns;
16 | private Integer connect;
17 | private Integer send;
18 | private Integer wait;
19 | private Integer receive;
20 | private Integer ssl;
21 | private String comment;
22 |
23 | /**
24 | * @return Time spent in a queue waiting for a network connection.
25 | * {@link #DEFAULT_TIME} if the timing does not apply to the current request.
26 | */
27 | public Integer getBlocked() {
28 | if (blocked == null) {
29 | return DEFAULT_TIME;
30 | }
31 | return blocked;
32 | }
33 |
34 | public void setBlocked(Integer blocked) {
35 | this.blocked = blocked;
36 | }
37 |
38 | /**
39 | * @return DNS resolution time. The time required to resolve a host name.
40 | * {@link #DEFAULT_TIME} if the timing does not apply to the current request.
41 | */
42 | public Integer getDns() {
43 | if (dns == null) {
44 | return DEFAULT_TIME;
45 | }
46 | return dns;
47 | }
48 |
49 | public void setDns(Integer dns) {
50 | this.dns = dns;
51 | }
52 |
53 | /**
54 | * @return Time required to create TCP connection.
55 | * {@link #DEFAULT_TIME} if the timing does not apply to the current request.
56 | */
57 | public Integer getConnect() {
58 | if (connect == null) {
59 | return DEFAULT_TIME;
60 | }
61 | return connect;
62 | }
63 |
64 | public void setConnect(Integer connect) {
65 | this.connect = connect;
66 | }
67 |
68 | /**
69 | * @return Time required to send HTTP request to the server, null if not present.
70 | */
71 | public Integer getSend() {
72 | return send;
73 | }
74 |
75 | public void setSend(Integer send) {
76 | this.send = send;
77 | }
78 |
79 | /**
80 | * @return Waiting for a response from the server, null if not present.
81 | */
82 | public Integer getWait() {
83 | return wait;
84 | }
85 |
86 | public void setWait(Integer wait) {
87 | this.wait = wait;
88 | }
89 |
90 | /**
91 | * @return Time required to read entire response from the server (or cache), null if not present.
92 | */
93 | public Integer getReceive() {
94 | return receive;
95 | }
96 |
97 | public void setReceive(Integer receive) {
98 | this.receive = receive;
99 | }
100 |
101 | /**
102 | * @return Time required for SSL/TLS negotiation.
103 | * If this field is defined then the time is also included in the connect field
104 | * (to ensure backward compatibility with HAR 1.1).
105 | * {@link #DEFAULT_TIME} if the timing does not apply to the current request.
106 | */
107 | public Integer getSsl() {
108 | if (ssl == null) {
109 | return DEFAULT_TIME;
110 | }
111 | return ssl;
112 | }
113 |
114 | public void setSsl(Integer ssl) {
115 | this.ssl = ssl;
116 | }
117 |
118 | /**
119 | * @return Comment provided by the user or application, null if not present.
120 | */
121 | public String getComment() {
122 | return comment;
123 | }
124 |
125 | public void setComment(String comment) {
126 | this.comment = comment;
127 | }
128 |
129 | @Override
130 | public boolean equals(Object o) {
131 | if (this == o) return true;
132 | if (o == null || getClass() != o.getClass()) return false;
133 | HarTiming harTiming = (HarTiming) o;
134 | return Objects.equals(blocked, harTiming.blocked) &&
135 | Objects.equals(dns, harTiming.dns) &&
136 | Objects.equals(connect, harTiming.connect) &&
137 | Objects.equals(send, harTiming.send) &&
138 | Objects.equals(wait, harTiming.wait) &&
139 | Objects.equals(receive, harTiming.receive) &&
140 | Objects.equals(ssl, harTiming.ssl) &&
141 | Objects.equals(comment, harTiming.comment);
142 | }
143 |
144 | @Override
145 | public int hashCode() {
146 | return Objects.hash(blocked, dns, connect, send, wait, receive, ssl, comment);
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarCache.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonFormat;
4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5 | import com.fasterxml.jackson.annotation.JsonInclude;
6 |
7 | import java.util.Date;
8 | import java.util.Objects;
9 |
10 | /**
11 | * Information about a request coming from browser cache.
12 | * @see specification
13 | */
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | @JsonIgnoreProperties(ignoreUnknown = true)
16 | public class HarCache {
17 |
18 | private HarCacheInfo beforeRequest;
19 | private HarCacheInfo afterRequest;
20 | private String comment;
21 |
22 | /**
23 | * @return State of the cache entry before the request, null if not present.
24 | */
25 | public HarCacheInfo getBeforeRequest() {
26 | return beforeRequest;
27 | }
28 |
29 | public void setBeforeRequest(HarCacheInfo beforeRequest) {
30 | this.beforeRequest = beforeRequest;
31 | }
32 |
33 | /**
34 | * @return State of the cache entry after the request, null if not present.
35 | */
36 | public HarCacheInfo getAfterRequest() {
37 | return afterRequest;
38 | }
39 |
40 | public void setAfterRequest(HarCacheInfo afterRequest) {
41 | this.afterRequest = afterRequest;
42 | }
43 |
44 | /**
45 | * @return Comment provided by the user or application, null if not present.
46 | */
47 | public String getComment() {
48 | return comment;
49 | }
50 |
51 | public void setComment(String comment) {
52 | this.comment = comment;
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o) return true;
58 | if (o == null || getClass() != o.getClass()) return false;
59 | HarCache harCache = (HarCache) o;
60 | return Objects.equals(beforeRequest, harCache.beforeRequest) &&
61 | Objects.equals(afterRequest, harCache.afterRequest) &&
62 | Objects.equals(comment, harCache.comment);
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | return Objects.hash(beforeRequest, afterRequest, comment);
68 | }
69 |
70 | /**
71 | * Information about a request coming from browser cache.
72 | * @see specification
73 | */
74 | @JsonInclude(JsonInclude.Include.NON_NULL)
75 | @JsonIgnoreProperties(ignoreUnknown = true)
76 | public static final class HarCacheInfo {
77 |
78 | private Date expires;
79 | private Date lastAccess;
80 | private String eTag;
81 | private Integer hitCount;
82 | private String comment;
83 |
84 | /**
85 | * @return Expiration time of entry, null if not present.
86 | */
87 | @JsonFormat(shape = JsonFormat.Shape.STRING)
88 | public Date getExpires() {
89 | return expires;
90 | }
91 |
92 | public void setExpires(Date expires) {
93 | this.expires = expires;
94 | }
95 |
96 | /**
97 | * @return Last time the entry was opened, null if not present.
98 | */
99 | @JsonFormat(shape = JsonFormat.Shape.STRING)
100 | public Date getLastAccess() {
101 | return lastAccess;
102 | }
103 |
104 | public void setLastAccess(Date lastAccess) {
105 | this.lastAccess = lastAccess;
106 | }
107 |
108 | /**
109 | * @return ETag, null if not present.
110 | */
111 | public String geteTag() {
112 | return eTag;
113 | }
114 |
115 | public void seteTag(String eTag) {
116 | this.eTag = eTag;
117 | }
118 |
119 | /**
120 | * @return Number of times the entry has been opened, null if not present.
121 | */
122 | public Integer getHitCount() {
123 | return hitCount;
124 | }
125 |
126 | public void setHitCount(Integer hitCount) {
127 | this.hitCount = hitCount;
128 | }
129 |
130 | /**
131 | * @return Comment provided by the user or application, null if not present.
132 | */
133 | public String getComment() {
134 | return comment;
135 | }
136 |
137 | public void setComment(String comment) {
138 | this.comment = comment;
139 | }
140 |
141 | @Override
142 | public boolean equals(Object o) {
143 | if (this == o) return true;
144 | if (o == null || getClass() != o.getClass()) return false;
145 | HarCacheInfo that = (HarCacheInfo) o;
146 | return Objects.equals(expires, that.expires) &&
147 | Objects.equals(lastAccess, that.lastAccess) &&
148 | Objects.equals(eTag, that.eTag) &&
149 | Objects.equals(hitCount, that.hitCount) &&
150 | Objects.equals(comment, that.comment);
151 | }
152 |
153 | @Override
154 | public int hashCode() {
155 | return Objects.hash(expires, lastAccess, eTag, hitCount, comment);
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarEntry.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonAnyGetter;
4 | import com.fasterxml.jackson.annotation.JsonAnySetter;
5 | import com.fasterxml.jackson.annotation.JsonFormat;
6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
7 | import com.fasterxml.jackson.annotation.JsonInclude;
8 |
9 | import java.util.Date;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Information about a single HTTP request.
16 | * @see specification
17 | */
18 | @JsonInclude(JsonInclude.Include.NON_NULL)
19 | @JsonIgnoreProperties(ignoreUnknown = true)
20 | public class HarEntry {
21 |
22 | private String pageref;
23 | private Date startedDateTime;
24 | private Integer time;
25 | private HarRequest request;
26 | private HarResponse response;
27 | private HarCache cache;
28 | private HarTiming timings;
29 | private String serverIPAddress;
30 | private String connection;
31 | private String comment;
32 | private Map additional = new HashMap<>();
33 |
34 | /**
35 | * @return Reference to parent page, to which the request belongs to, null if not present.
36 | */
37 | public String getPageref() {
38 | return pageref;
39 | }
40 |
41 | public void setPageref(String pageref) {
42 | this.pageref = pageref;
43 | }
44 |
45 | /**
46 | * @return Start time of request, null if not present.
47 | */
48 | @JsonFormat(shape = JsonFormat.Shape.STRING)
49 | public Date getStartedDateTime() {
50 | return startedDateTime;
51 | }
52 |
53 | public void setStartedDateTime(Date startedDateTime) {
54 | this.startedDateTime = startedDateTime;
55 | }
56 |
57 | /**
58 | * @return Total request time (in ms), null if not present.
59 | */
60 | public Integer getTime() {
61 | return time;
62 | }
63 |
64 | public void setTime(Integer time) {
65 | this.time = time;
66 | }
67 |
68 | /**
69 | * @return Detailed request information.
70 | */
71 | public HarRequest getRequest() {
72 | if (request == null) {
73 | request = new HarRequest();
74 | }
75 | return request;
76 | }
77 |
78 | public void setRequest(HarRequest request) {
79 | this.request = request;
80 | }
81 |
82 | /**
83 | * @return Detailed response information.
84 | */
85 | public HarResponse getResponse() {
86 | if (response == null) {
87 | response = new HarResponse();
88 | }
89 | return response;
90 | }
91 |
92 | public void setResponse(HarResponse response) {
93 | this.response = response;
94 | }
95 |
96 | /**
97 | * @return Information about cache usage.
98 | */
99 | public HarCache getCache() {
100 | if (cache == null) {
101 | cache = new HarCache();
102 | }
103 | return cache;
104 | }
105 |
106 | public void setCache(HarCache cache) {
107 | this.cache = cache;
108 | }
109 |
110 | /**
111 | * @return Detailed information about request/response timings.
112 | */
113 | public HarTiming getTimings() {
114 | if (timings == null) {
115 | timings = new HarTiming();
116 | }
117 | return timings;
118 | }
119 |
120 | public void setTimings(HarTiming timings) {
121 | this.timings = timings;
122 | }
123 |
124 | /**
125 | * @return Server IP address (result of DNS resolution), null if not present.
126 | */
127 | public String getServerIPAddress() {
128 | return serverIPAddress;
129 | }
130 |
131 | public void setServerIPAddress(String serverIPAddress) {
132 | this.serverIPAddress = serverIPAddress;
133 | }
134 |
135 | /**
136 | * @return Unique ID of TCP/IP connection, null if not present.
137 | */
138 | public String getConnection() {
139 | return connection;
140 | }
141 |
142 | public void setConnection(String connection) {
143 | this.connection = connection;
144 | }
145 |
146 | /**
147 | * @return Comment provided by the user or application, null if not present.
148 | */
149 | public String getComment() {
150 | return comment;
151 | }
152 |
153 | public void setComment(String comment) {
154 | this.comment = comment;
155 | }
156 |
157 | @JsonAnyGetter
158 | public Map getAdditional() {
159 | return additional;
160 | }
161 |
162 | @JsonAnySetter
163 | public void setAdditionalField(String name, Object value) {
164 | this.additional.put(name, value);
165 | }
166 |
167 | @Override
168 | public boolean equals(Object o) {
169 | if (this == o) return true;
170 | if (o == null || getClass() != o.getClass()) return false;
171 | HarEntry harEntry = (HarEntry) o;
172 | return Objects.equals(pageref, harEntry.pageref) &&
173 | Objects.equals(startedDateTime, harEntry.startedDateTime) &&
174 | Objects.equals(time, harEntry.time) &&
175 | Objects.equals(request, harEntry.request) &&
176 | Objects.equals(response, harEntry.response) &&
177 | Objects.equals(cache, harEntry.cache) &&
178 | Objects.equals(timings, harEntry.timings) &&
179 | Objects.equals(serverIPAddress, harEntry.serverIPAddress) &&
180 | Objects.equals(connection, harEntry.connection) &&
181 | Objects.equals(comment, harEntry.comment) &&
182 | Objects.equals(additional, harEntry.additional);
183 | }
184 |
185 | @Override
186 | public int hashCode() {
187 | return Objects.hash(pageref, startedDateTime, time, request, response, cache, timings, serverIPAddress,
188 | connection, comment, additional);
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarResponse.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonAnyGetter;
4 | import com.fasterxml.jackson.annotation.JsonAnySetter;
5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
6 | import com.fasterxml.jackson.annotation.JsonInclude;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | @JsonInclude(JsonInclude.Include.NON_NULL)
15 | @JsonIgnoreProperties(ignoreUnknown = true)
16 | public class HarResponse {
17 |
18 | protected static final Long DEFAULT_SIZE = -1L;
19 |
20 | private HttpStatus status;
21 | private String statusText;
22 | private String httpVersion;
23 | private List cookies;
24 | private List headers;
25 | private HarContent content;
26 | private String redirectURL;
27 | private Long headersSize;
28 | private Long bodySize;
29 | private String comment;
30 | private Map additional = new HashMap<>();
31 |
32 | /**
33 | * @return Response status, null if not present.
34 | */
35 | public int getStatus() {
36 | if (status == null) {
37 | status = HttpStatus.UNKNOWN_HTTP_STATUS;
38 | }
39 | return status.getCode();
40 | }
41 |
42 | public void setStatus(int status) {
43 | this.status = HttpStatus.byCode(status);
44 | }
45 |
46 | /**
47 | * @return Response status description, null if not present.
48 | */
49 | public String getStatusText() {
50 | return statusText;
51 | }
52 |
53 | public void setStatusText(String statusText) {
54 | this.statusText = statusText;
55 | }
56 |
57 | /**
58 | * @return Response HTTP Version, null if not present.
59 | */
60 | public String getHttpVersion() {
61 | return httpVersion;
62 | }
63 |
64 | public void setHttpVersion(String httpVersion) {
65 | this.httpVersion = httpVersion;
66 | }
67 |
68 | /**
69 | * @return List of cookie objects.
70 | */
71 | public List getCookies() {
72 | if (cookies == null) {
73 | cookies = new ArrayList<>();
74 | }
75 | return cookies;
76 | }
77 |
78 | public void setCookies(List cookies) {
79 | this.cookies = cookies;
80 | }
81 |
82 | /**
83 | * @return List of header objects.
84 | */
85 | public List getHeaders() {
86 | if (headers == null) {
87 | headers = new ArrayList<>();
88 | }
89 | return headers;
90 | }
91 |
92 | public void setHeaders(List headers) {
93 | this.headers = headers;
94 | }
95 |
96 | /**
97 | * @return Details about the response body.
98 | */
99 | public HarContent getContent() {
100 | if (content == null) {
101 | content = new HarContent();
102 | }
103 | return content;
104 | }
105 |
106 | public void setContent(HarContent content) {
107 | this.content = content;
108 | }
109 |
110 | /**
111 | * @return Redirection target URL from the Location response header, null if not present.
112 | */
113 | public String getRedirectURL() {
114 | return redirectURL;
115 | }
116 |
117 | public void setRedirectURL(String redirectURL) {
118 | this.redirectURL = redirectURL;
119 | }
120 |
121 | /**
122 | * @return Total number of bytes from the start of the HTTP response message until (and including) the double
123 | * CRLF before the body. {@link #DEFAULT_SIZE} if the info is not available.
124 | */
125 | public Long getHeadersSize() {
126 | if (headersSize == null) {
127 | return DEFAULT_SIZE;
128 | }
129 | return headersSize;
130 | }
131 |
132 | public void setHeadersSize(Long headersSize) {
133 | this.headersSize = headersSize;
134 | }
135 |
136 | /**
137 | * @return Size of the received response body in bytes.
138 | * Set to zero in case of responses coming from the cache (304).
139 | * {@link #DEFAULT_SIZE} if the info is not available.
140 | */
141 | public Long getBodySize() {
142 | if (bodySize == null) {
143 | return DEFAULT_SIZE;
144 | }
145 | return bodySize;
146 | }
147 |
148 | public void setBodySize(Long bodySize) {
149 | this.bodySize = bodySize;
150 | }
151 |
152 | /**
153 | * @return Comment provided by the user or application, null if not present.
154 | */
155 | public String getComment() {
156 | return comment;
157 | }
158 |
159 | public void setComment(String comment) {
160 | this.comment = comment;
161 | }
162 |
163 | @JsonAnyGetter
164 | public Map getAdditional() {
165 | return additional;
166 | }
167 |
168 | @JsonAnySetter
169 | public void setAdditionalField(String name, Object value) {
170 | this.additional.put(name, value);
171 | }
172 |
173 | @Override
174 | public boolean equals(Object o) {
175 | if (this == o) return true;
176 | if (o == null || getClass() != o.getClass()) return false;
177 | HarResponse that = (HarResponse) o;
178 | return status == that.status &&
179 | Objects.equals(statusText, that.statusText) &&
180 | Objects.equals(httpVersion, that.httpVersion) &&
181 | Objects.equals(cookies, that.cookies) &&
182 | Objects.equals(headers, that.headers) &&
183 | Objects.equals(content, that.content) &&
184 | Objects.equals(redirectURL, that.redirectURL) &&
185 | Objects.equals(headersSize, that.headersSize) &&
186 | Objects.equals(bodySize, that.bodySize) &&
187 | Objects.equals(comment, that.comment) &&
188 | Objects.equals(additional, that.additional);
189 | }
190 |
191 | @Override
192 | public int hashCode() {
193 | return Objects.hash(status, statusText, httpVersion, cookies, headers, content, redirectURL, headersSize,
194 | bodySize, comment, additional);
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/java/de/sstoehr/harreader/model/HarRequest.java:
--------------------------------------------------------------------------------
1 | package de.sstoehr.harreader.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonAnyGetter;
4 | import com.fasterxml.jackson.annotation.JsonAnySetter;
5 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
6 | import com.fasterxml.jackson.annotation.JsonInclude;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Information about a performed request.
16 | * @see specification
17 | */
18 | @JsonInclude(JsonInclude.Include.NON_NULL)
19 | @JsonIgnoreProperties(ignoreUnknown = true)
20 | public class HarRequest {
21 |
22 | protected static final Long DEFAULT_SIZE = -1L;
23 |
24 | private HttpMethod method;
25 | private String url;
26 | private String httpVersion;
27 | private List cookies;
28 | private List headers;
29 | private List queryString;
30 | private HarPostData postData;
31 | private Long headersSize;
32 | private Long bodySize;
33 | private String comment;
34 | private Map additional = new HashMap<>();
35 |
36 | /**
37 | * @return Request method, null if not present.
38 | */
39 | public HttpMethod getMethod() {
40 | return method;
41 | }
42 |
43 | public void setMethod(HttpMethod method) {
44 | this.method = method;
45 | }
46 |
47 | /**
48 | * @return Absolute URL of the request (fragments are not included), null if not present.
49 | */
50 | public String getUrl() {
51 | return url;
52 | }
53 |
54 | public void setUrl(String url) {
55 | this.url = url;
56 | }
57 |
58 | /**
59 | * @return Request HTTP Version, null if not present.
60 | */
61 | public String getHttpVersion() {
62 | return httpVersion;
63 | }
64 |
65 | public void setHttpVersion(String httpVersion) {
66 | this.httpVersion = httpVersion;
67 | }
68 |
69 | /**
70 | * @return List of cookie objects.
71 | */
72 | public List getCookies() {
73 | if (cookies == null) {
74 | cookies = new ArrayList<>();
75 | }
76 | return cookies;
77 | }
78 |
79 | public void setCookies(List cookies) {
80 | this.cookies = cookies;
81 | }
82 |
83 | /**
84 | * @return List of header objects.
85 | */
86 | public List getHeaders() {
87 | if (headers == null) {
88 | headers = new ArrayList<>();
89 | }
90 | return headers;
91 | }
92 |
93 | public void setHeaders(List headers) {
94 | this.headers = headers;
95 | }
96 |
97 | /**
98 | * @return List of query parameter objects.
99 | */
100 | public List getQueryString() {
101 | if (queryString == null) {
102 | queryString = new ArrayList<>();
103 | }
104 | return queryString;
105 | }
106 |
107 | public void setQueryString(List queryString) {
108 | this.queryString = queryString;
109 | }
110 |
111 | /**
112 | * @return Posted data info.
113 | */
114 | public HarPostData getPostData() {
115 | if (postData == null) {
116 | postData = new HarPostData();
117 | }
118 | return postData;
119 | }
120 |
121 | public void setPostData(HarPostData postData) {
122 | this.postData = postData;
123 | }
124 |
125 | /**
126 | * @return Total number of bytes from the start of the HTTP request message until (and including) the double
127 | * CRLF before the body. {@link #DEFAULT_SIZE} if the info is not available.
128 | */
129 | public Long getHeadersSize() {
130 | if (headersSize == null) {
131 | return DEFAULT_SIZE;
132 | }
133 | return headersSize;
134 | }
135 |
136 | public void setHeadersSize(Long headersSize) {
137 | this.headersSize = headersSize;
138 | }
139 |
140 | /**
141 | * @return Size of the request body (POST data payload) in bytes.
142 | * {@link #DEFAULT_SIZE} if the info is not available.
143 | */
144 | public Long getBodySize() {
145 | if (bodySize == null) {
146 | return DEFAULT_SIZE;
147 | }
148 | return bodySize;
149 | }
150 |
151 | public void setBodySize(Long bodySize) {
152 | this.bodySize = bodySize;
153 | }
154 |
155 | /**
156 | * @return Comment provided by the user or application, null if not present.
157 | */
158 | public String getComment() {
159 | return comment;
160 | }
161 |
162 | public void setComment(String comment) {
163 | this.comment = comment;
164 | }
165 |
166 | @JsonAnyGetter
167 | public Map getAdditional() {
168 | return additional;
169 | }
170 |
171 | @JsonAnySetter
172 | public void setAdditionalField(String name, Object value) {
173 | this.additional.put(name, value);
174 | }
175 |
176 | @Override
177 | public boolean equals(Object o) {
178 | if (this == o) return true;
179 | if (o == null || getClass() != o.getClass()) return false;
180 | HarRequest that = (HarRequest) o;
181 | return method == that.method &&
182 | Objects.equals(url, that.url) &&
183 | Objects.equals(httpVersion, that.httpVersion) &&
184 | Objects.equals(cookies, that.cookies) &&
185 | Objects.equals(headers, that.headers) &&
186 | Objects.equals(queryString, that.queryString) &&
187 | Objects.equals(postData, that.postData) &&
188 | Objects.equals(headersSize, that.headersSize) &&
189 | Objects.equals(bodySize, that.bodySize) &&
190 | Objects.equals(comment, that.comment) &&
191 | Objects.equals(additional, that.additional);
192 | }
193 |
194 | @Override
195 | public int hashCode() {
196 | return Objects.hash(method, url, httpVersion, cookies, headers, queryString, postData, headersSize,
197 | bodySize, comment, additional);
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/src/test/resources/sstoehr.har:
--------------------------------------------------------------------------------
1 | {
2 | "log": {
3 | "version": "1.1",
4 | "creator": {
5 | "name": "Firebug",
6 | "version": "1.12"
7 | },
8 | "browser": {
9 | "name": "Firefox",
10 | "version": "26.0"
11 | },
12 | "pages": [
13 | {
14 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
15 | "id": "page_3",
16 | "title": "Home — Sebastian Stöhr",
17 | "pageTimings": {
18 | "onContentLoad": 3910,
19 | "onLoad": -1
20 | }
21 | }
22 | ],
23 | "entries": [
24 | {
25 | "pageref": "page_3",
26 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
27 | "time": 3804,
28 | "request": {
29 | "method": "GET",
30 | "url": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css",
31 | "httpVersion": "HTTP/1.1",
32 | "cookies": [],
33 | "headers": [
34 | {
35 | "name": "Host",
36 | "value": "www.sebastianstoehr.de"
37 | },
38 | {
39 | "name": "User-Agent",
40 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
41 | },
42 | {
43 | "name": "Accept",
44 | "value": "text/css,*/*;q=0.1"
45 | },
46 | {
47 | "name": "Accept-Language",
48 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
49 | },
50 | {
51 | "name": "Accept-Encoding",
52 | "value": "gzip, deflate"
53 | },
54 | {
55 | "name": "DNT",
56 | "value": "1"
57 | },
58 | {
59 | "name": "Referer",
60 | "value": "http://www.sebastianstoehr.de/"
61 | },
62 | {
63 | "name": "Connection",
64 | "value": "keep-alive"
65 | }
66 | ],
67 | "queryString": [],
68 | "headersSize": 676,
69 | "bodySize": -1
70 | },
71 | "response": {
72 | "status": 200,
73 | "statusText": "OK",
74 | "httpVersion": "HTTP/1.1",
75 | "cookies": [],
76 | "headers": [
77 | {
78 | "name": "Date",
79 | "value": "Sun, 26 Jan 2014 17:37:44 GMT"
80 | },
81 | {
82 | "name": "Server",
83 | "value": "Apache"
84 | },
85 | {
86 | "name": "Last-Modified",
87 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
88 | },
89 | {
90 | "name": "Accept-Ranges",
91 | "value": "bytes"
92 | },
93 | {
94 | "name": "Content-Length",
95 | "value": "3412"
96 | },
97 | {
98 | "name": "Cache-Control",
99 | "value": "max-age=15552000"
100 | },
101 | {
102 | "name": "Expires",
103 | "value": "Fri, 25 Jul 2014 17:37:44 GMT"
104 | },
105 | {
106 | "name": "Vary",
107 | "value": "Accept-Encoding"
108 | },
109 | {
110 | "name": "Keep-Alive",
111 | "value": "timeout=2, max=200"
112 | },
113 | {
114 | "name": "Connection",
115 | "value": "Keep-Alive"
116 | },
117 | {
118 | "name": "Content-Type",
119 | "value": "text/css"
120 | },
121 | {
122 | "name": "Content-Encoding",
123 | "value": "gzip"
124 | }
125 | ],
126 | "content": {
127 | "mimeType": "text/css",
128 | "size": 12647,
129 | "text": "--- REMOVED ---\n"
130 | },
131 | "redirectURL": "",
132 | "headersSize": 362,
133 | "bodySize": 3412
134 | },
135 | "cache": {},
136 | "timings": {
137 | "blocked": 5,
138 | "dns": 0,
139 | "connect": 0,
140 | "send": 0,
141 | "wait": 3778,
142 | "receive": 21
143 | },
144 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
145 | "connection": "80"
146 | },
147 | {
148 | "pageref": "page_3",
149 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
150 | "time": 9092,
151 | "request": {
152 | "method": "GET",
153 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg",
154 | "httpVersion": "HTTP/1.1",
155 | "cookies": [],
156 | "headers": [
157 | {
158 | "name": "Host",
159 | "value": "www.sebastianstoehr.de"
160 | },
161 | {
162 | "name": "User-Agent",
163 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
164 | },
165 | {
166 | "name": "Accept",
167 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
168 | },
169 | {
170 | "name": "Accept-Language",
171 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
172 | },
173 | {
174 | "name": "Accept-Encoding",
175 | "value": "gzip, deflate"
176 | },
177 | {
178 | "name": "DNT",
179 | "value": "1"
180 | },
181 | {
182 | "name": "Referer",
183 | "value": "http://www.sebastianstoehr.de/"
184 | },
185 | {
186 | "name": "Connection",
187 | "value": "keep-alive"
188 | }
189 | ],
190 | "queryString": [],
191 | "headersSize": 704,
192 | "bodySize": -1
193 | },
194 | "response": {
195 | "status": 200,
196 | "statusText": "OK",
197 | "httpVersion": "HTTP/1.1",
198 | "cookies": [],
199 | "headers": [
200 | {
201 | "name": "Date",
202 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
203 | },
204 | {
205 | "name": "Server",
206 | "value": "Apache"
207 | },
208 | {
209 | "name": "Last-Modified",
210 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
211 | },
212 | {
213 | "name": "Accept-Ranges",
214 | "value": "bytes"
215 | },
216 | {
217 | "name": "Content-Length",
218 | "value": "16997"
219 | },
220 | {
221 | "name": "Cache-Control",
222 | "value": "max-age=15552000"
223 | },
224 | {
225 | "name": "Expires",
226 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
227 | },
228 | {
229 | "name": "Keep-Alive",
230 | "value": "timeout=2, max=200"
231 | },
232 | {
233 | "name": "Connection",
234 | "value": "Keep-Alive"
235 | },
236 | {
237 | "name": "Content-Type",
238 | "value": "image/jpeg"
239 | }
240 | ],
241 | "content": {
242 | "mimeType": "image/jpeg",
243 | "size": 132,
244 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg"
245 | },
246 | "redirectURL": "",
247 | "headersSize": 318,
248 | "bodySize": 16997
249 | },
250 | "cache": {},
251 | "timings": {
252 | "blocked": 3804,
253 | "dns": 0,
254 | "connect": 0,
255 | "send": 0,
256 | "wait": 5209,
257 | "receive": 79
258 | },
259 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
260 | "connection": "80"
261 | },
262 | {
263 | "pageref": "page_3",
264 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
265 | "time": 9139,
266 | "request": {
267 | "method": "GET",
268 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg",
269 | "httpVersion": "HTTP/1.1",
270 | "cookies": [],
271 | "headers": [
272 | {
273 | "name": "Host",
274 | "value": "www.sebastianstoehr.de"
275 | },
276 | {
277 | "name": "User-Agent",
278 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
279 | },
280 | {
281 | "name": "Accept",
282 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
283 | },
284 | {
285 | "name": "Accept-Language",
286 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
287 | },
288 | {
289 | "name": "Accept-Encoding",
290 | "value": "gzip, deflate"
291 | },
292 | {
293 | "name": "DNT",
294 | "value": "1"
295 | },
296 | {
297 | "name": "Referer",
298 | "value": "http://www.sebastianstoehr.de/"
299 | },
300 | {
301 | "name": "Connection",
302 | "value": "keep-alive"
303 | }
304 | ],
305 | "queryString": [],
306 | "headersSize": 707,
307 | "bodySize": -1
308 | },
309 | "response": {
310 | "status": 200,
311 | "statusText": "OK",
312 | "httpVersion": "HTTP/1.1",
313 | "cookies": [],
314 | "headers": [
315 | {
316 | "name": "Date",
317 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
318 | },
319 | {
320 | "name": "Server",
321 | "value": "Apache"
322 | },
323 | {
324 | "name": "Last-Modified",
325 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
326 | },
327 | {
328 | "name": "Accept-Ranges",
329 | "value": "bytes"
330 | },
331 | {
332 | "name": "Content-Length",
333 | "value": "28351"
334 | },
335 | {
336 | "name": "Cache-Control",
337 | "value": "max-age=15552000"
338 | },
339 | {
340 | "name": "Expires",
341 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
342 | },
343 | {
344 | "name": "Keep-Alive",
345 | "value": "timeout=2, max=200"
346 | },
347 | {
348 | "name": "Connection",
349 | "value": "Keep-Alive"
350 | },
351 | {
352 | "name": "Content-Type",
353 | "value": "image/jpeg"
354 | }
355 | ],
356 | "content": {
357 | "mimeType": "image/jpeg",
358 | "size": 135,
359 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg"
360 | },
361 | "redirectURL": "",
362 | "headersSize": 318,
363 | "bodySize": 28351
364 | },
365 | "cache": {},
366 | "timings": {
367 | "blocked": 3804,
368 | "dns": 0,
369 | "connect": 0,
370 | "send": 0,
371 | "wait": 5240,
372 | "receive": 95
373 | },
374 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
375 | "connection": "80"
376 | },
377 | {
378 | "pageref": "page_3",
379 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
380 | "time": 9164,
381 | "request": {
382 | "method": "GET",
383 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg",
384 | "httpVersion": "HTTP/1.1",
385 | "cookies": [],
386 | "headers": [
387 | {
388 | "name": "Host",
389 | "value": "www.sebastianstoehr.de"
390 | },
391 | {
392 | "name": "User-Agent",
393 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
394 | },
395 | {
396 | "name": "Accept",
397 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
398 | },
399 | {
400 | "name": "Accept-Language",
401 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
402 | },
403 | {
404 | "name": "Accept-Encoding",
405 | "value": "gzip, deflate"
406 | },
407 | {
408 | "name": "DNT",
409 | "value": "1"
410 | },
411 | {
412 | "name": "Referer",
413 | "value": "http://www.sebastianstoehr.de/"
414 | },
415 | {
416 | "name": "Connection",
417 | "value": "keep-alive"
418 | }
419 | ],
420 | "queryString": [],
421 | "headersSize": 701,
422 | "bodySize": -1
423 | },
424 | "response": {
425 | "status": 200,
426 | "statusText": "OK",
427 | "httpVersion": "HTTP/1.1",
428 | "cookies": [],
429 | "headers": [
430 | {
431 | "name": "Date",
432 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
433 | },
434 | {
435 | "name": "Server",
436 | "value": "Apache"
437 | },
438 | {
439 | "name": "Last-Modified",
440 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
441 | },
442 | {
443 | "name": "Accept-Ranges",
444 | "value": "bytes"
445 | },
446 | {
447 | "name": "Content-Length",
448 | "value": "73064"
449 | },
450 | {
451 | "name": "Cache-Control",
452 | "value": "max-age=15552000"
453 | },
454 | {
455 | "name": "Expires",
456 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
457 | },
458 | {
459 | "name": "Keep-Alive",
460 | "value": "timeout=2, max=200"
461 | },
462 | {
463 | "name": "Connection",
464 | "value": "Keep-Alive"
465 | },
466 | {
467 | "name": "Content-Type",
468 | "value": "image/jpeg"
469 | }
470 | ],
471 | "content": {
472 | "mimeType": "image/jpeg",
473 | "size": 129,
474 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg"
475 | },
476 | "redirectURL": "",
477 | "headersSize": 318,
478 | "bodySize": 73064
479 | },
480 | "cache": {},
481 | "timings": {
482 | "blocked": 3804,
483 | "dns": 0,
484 | "connect": 0,
485 | "send": 0,
486 | "wait": 5217,
487 | "receive": 143
488 | },
489 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
490 | "connection": "80"
491 | },
492 | {
493 | "pageref": "page_3",
494 | "startedDateTime": "2014-01-26T18:37:43.814+01:00",
495 | "time": 9156,
496 | "request": {
497 | "method": "GET",
498 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg",
499 | "httpVersion": "HTTP/1.1",
500 | "cookies": [],
501 | "headers": [
502 | {
503 | "name": "Host",
504 | "value": "www.sebastianstoehr.de"
505 | },
506 | {
507 | "name": "User-Agent",
508 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
509 | },
510 | {
511 | "name": "Accept",
512 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
513 | },
514 | {
515 | "name": "Accept-Language",
516 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
517 | },
518 | {
519 | "name": "Accept-Encoding",
520 | "value": "gzip, deflate"
521 | },
522 | {
523 | "name": "DNT",
524 | "value": "1"
525 | },
526 | {
527 | "name": "Referer",
528 | "value": "http://www.sebastianstoehr.de/"
529 | },
530 | {
531 | "name": "Connection",
532 | "value": "keep-alive"
533 | }
534 | ],
535 | "queryString": [],
536 | "headersSize": 705,
537 | "bodySize": -1
538 | },
539 | "response": {
540 | "status": 200,
541 | "statusText": "OK",
542 | "httpVersion": "HTTP/1.1",
543 | "cookies": [],
544 | "headers": [
545 | {
546 | "name": "Date",
547 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
548 | },
549 | {
550 | "name": "Server",
551 | "value": "Apache"
552 | },
553 | {
554 | "name": "Last-Modified",
555 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
556 | },
557 | {
558 | "name": "Accept-Ranges",
559 | "value": "bytes"
560 | },
561 | {
562 | "name": "Content-Length",
563 | "value": "49555"
564 | },
565 | {
566 | "name": "Cache-Control",
567 | "value": "max-age=15552000"
568 | },
569 | {
570 | "name": "Expires",
571 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
572 | },
573 | {
574 | "name": "Keep-Alive",
575 | "value": "timeout=2, max=200"
576 | },
577 | {
578 | "name": "Connection",
579 | "value": "Keep-Alive"
580 | },
581 | {
582 | "name": "Content-Type",
583 | "value": "image/jpeg"
584 | }
585 | ],
586 | "content": {
587 | "mimeType": "image/jpeg",
588 | "size": 133,
589 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg"
590 | },
591 | "redirectURL": "",
592 | "headersSize": 318,
593 | "bodySize": 49555
594 | },
595 | "cache": {},
596 | "timings": {
597 | "blocked": 3803,
598 | "dns": 0,
599 | "connect": 0,
600 | "send": 0,
601 | "wait": 5222,
602 | "receive": 131
603 | },
604 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
605 | "connection": "80"
606 | },
607 | {
608 | "pageref": "page_3",
609 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
610 | "time": 5010,
611 | "request": {
612 | "method": "GET",
613 | "url": "http://www.sebastianstoehr.de/res/images/logo.png",
614 | "httpVersion": "HTTP/1.1",
615 | "cookies": [],
616 | "headers": [
617 | {
618 | "name": "Host",
619 | "value": "www.sebastianstoehr.de"
620 | },
621 | {
622 | "name": "User-Agent",
623 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
624 | },
625 | {
626 | "name": "Accept",
627 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
628 | },
629 | {
630 | "name": "Accept-Language",
631 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
632 | },
633 | {
634 | "name": "Accept-Encoding",
635 | "value": "gzip, deflate"
636 | },
637 | {
638 | "name": "DNT",
639 | "value": "1"
640 | },
641 | {
642 | "name": "Referer",
643 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
644 | },
645 | {
646 | "name": "Connection",
647 | "value": "keep-alive"
648 | }
649 | ],
650 | "queryString": [],
651 | "headersSize": 710,
652 | "bodySize": -1
653 | },
654 | "response": {
655 | "status": 200,
656 | "statusText": "OK",
657 | "httpVersion": "HTTP/1.1",
658 | "cookies": [],
659 | "headers": [
660 | {
661 | "name": "Date",
662 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
663 | },
664 | {
665 | "name": "Server",
666 | "value": "Apache"
667 | },
668 | {
669 | "name": "Last-Modified",
670 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
671 | },
672 | {
673 | "name": "Accept-Ranges",
674 | "value": "bytes"
675 | },
676 | {
677 | "name": "Content-Length",
678 | "value": "717"
679 | },
680 | {
681 | "name": "Cache-Control",
682 | "value": "max-age=15552000"
683 | },
684 | {
685 | "name": "Expires",
686 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
687 | },
688 | {
689 | "name": "Keep-Alive",
690 | "value": "timeout=2, max=199"
691 | },
692 | {
693 | "name": "Connection",
694 | "value": "Keep-Alive"
695 | },
696 | {
697 | "name": "Content-Type",
698 | "value": "image/png"
699 | }
700 | ],
701 | "content": {
702 | "mimeType": "image/png",
703 | "size": 91,
704 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/logo.png"
705 | },
706 | "redirectURL": "",
707 | "headersSize": 315,
708 | "bodySize": 717
709 | },
710 | "cache": {},
711 | "timings": {
712 | "blocked": 0,
713 | "dns": 0,
714 | "connect": 0,
715 | "send": 0,
716 | "wait": 5010,
717 | "receive": 0
718 | },
719 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
720 | "connection": "80"
721 | },
722 | {
723 | "pageref": "page_3",
724 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
725 | "time": 5032,
726 | "request": {
727 | "method": "GET",
728 | "url": "http://www.sebastianstoehr.de/res/images/socialbar.png",
729 | "httpVersion": "HTTP/1.1",
730 | "cookies": [],
731 | "headers": [
732 | {
733 | "name": "Host",
734 | "value": "www.sebastianstoehr.de"
735 | },
736 | {
737 | "name": "User-Agent",
738 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
739 | },
740 | {
741 | "name": "Accept",
742 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
743 | },
744 | {
745 | "name": "Accept-Language",
746 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
747 | },
748 | {
749 | "name": "Accept-Encoding",
750 | "value": "gzip, deflate"
751 | },
752 | {
753 | "name": "DNT",
754 | "value": "1"
755 | },
756 | {
757 | "name": "Referer",
758 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
759 | },
760 | {
761 | "name": "Connection",
762 | "value": "keep-alive"
763 | }
764 | ],
765 | "queryString": [],
766 | "headersSize": 715,
767 | "bodySize": -1
768 | },
769 | "response": {
770 | "status": 200,
771 | "statusText": "OK",
772 | "httpVersion": "HTTP/1.1",
773 | "cookies": [],
774 | "headers": [
775 | {
776 | "name": "Date",
777 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
778 | },
779 | {
780 | "name": "Server",
781 | "value": "Apache"
782 | },
783 | {
784 | "name": "Last-Modified",
785 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
786 | },
787 | {
788 | "name": "Accept-Ranges",
789 | "value": "bytes"
790 | },
791 | {
792 | "name": "Content-Length",
793 | "value": "2772"
794 | },
795 | {
796 | "name": "Cache-Control",
797 | "value": "max-age=15552000"
798 | },
799 | {
800 | "name": "Expires",
801 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
802 | },
803 | {
804 | "name": "Keep-Alive",
805 | "value": "timeout=2, max=200"
806 | },
807 | {
808 | "name": "Connection",
809 | "value": "Keep-Alive"
810 | },
811 | {
812 | "name": "Content-Type",
813 | "value": "image/png"
814 | }
815 | ],
816 | "content": {
817 | "mimeType": "image/png",
818 | "size": 96,
819 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/socialbar.png"
820 | },
821 | "redirectURL": "",
822 | "headersSize": 316,
823 | "bodySize": 2772
824 | },
825 | "cache": {},
826 | "timings": {
827 | "blocked": 0,
828 | "dns": 0,
829 | "connect": 29,
830 | "send": 0,
831 | "wait": 4980,
832 | "receive": 23
833 | },
834 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
835 | "connection": "80"
836 | },
837 | {
838 | "pageref": "page_3",
839 | "startedDateTime": "2014-01-26T18:37:47.711+01:00",
840 | "time": 5057,
841 | "request": {
842 | "method": "GET",
843 | "url": "http://www.sebastianstoehr.de/assets/app-d6d60b5cc834e6a9ce6fbfee22da998f.js",
844 | "httpVersion": "HTTP/1.1",
845 | "cookies": [],
846 | "headers": [
847 | {
848 | "name": "Host",
849 | "value": "www.sebastianstoehr.de"
850 | },
851 | {
852 | "name": "User-Agent",
853 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
854 | },
855 | {
856 | "name": "Accept",
857 | "value": "*/*"
858 | },
859 | {
860 | "name": "Accept-Language",
861 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
862 | },
863 | {
864 | "name": "Accept-Encoding",
865 | "value": "gzip, deflate"
866 | },
867 | {
868 | "name": "DNT",
869 | "value": "1"
870 | },
871 | {
872 | "name": "Referer",
873 | "value": "http://www.sebastianstoehr.de/"
874 | },
875 | {
876 | "name": "Connection",
877 | "value": "keep-alive"
878 | }
879 | ],
880 | "queryString": [],
881 | "headersSize": 660,
882 | "bodySize": -1
883 | },
884 | "response": {
885 | "status": 200,
886 | "statusText": "OK",
887 | "httpVersion": "HTTP/1.1",
888 | "cookies": [],
889 | "headers": [
890 | {
891 | "name": "Date",
892 | "value": "Sun, 26 Jan 2014 17:37:53 GMT"
893 | },
894 | {
895 | "name": "Server",
896 | "value": "Apache"
897 | },
898 | {
899 | "name": "Last-Modified",
900 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
901 | },
902 | {
903 | "name": "Accept-Ranges",
904 | "value": "bytes"
905 | },
906 | {
907 | "name": "Content-Length",
908 | "value": "4453"
909 | },
910 | {
911 | "name": "Cache-Control",
912 | "value": "max-age=15552000"
913 | },
914 | {
915 | "name": "Expires",
916 | "value": "Fri, 25 Jul 2014 17:37:53 GMT"
917 | },
918 | {
919 | "name": "Vary",
920 | "value": "Accept-Encoding"
921 | },
922 | {
923 | "name": "Keep-Alive",
924 | "value": "timeout=2, max=198"
925 | },
926 | {
927 | "name": "Connection",
928 | "value": "Keep-Alive"
929 | },
930 | {
931 | "name": "Content-Type",
932 | "value": "text/javascript"
933 | },
934 | {
935 | "name": "Content-Encoding",
936 | "value": "gzip"
937 | }
938 | ],
939 | "content": {
940 | "mimeType": "text/javascript",
941 | "size": 11676,
942 | "text": "--- REMOVED ---\n"
943 | },
944 | "redirectURL": "",
945 | "headersSize": 369,
946 | "bodySize": 4453
947 | },
948 | "cache": {},
949 | "timings": {
950 | "blocked": 5000,
951 | "dns": 0,
952 | "connect": 0,
953 | "send": 0,
954 | "wait": 55,
955 | "receive": 2
956 | },
957 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
958 | "connection": "80"
959 | }
960 | ]
961 | }
962 | }
--------------------------------------------------------------------------------
/src/test/resources/sstoehr.invalid-date.har:
--------------------------------------------------------------------------------
1 | {
2 | "log": {
3 | "version": "1.1",
4 | "creator": {
5 | "name": "Firebug",
6 | "version": "1.12"
7 | },
8 | "browser": {
9 | "name": "Firefox",
10 | "version": "26.0"
11 | },
12 | "pages": [
13 | {
14 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
15 | "id": "page_3",
16 | "title": "Home — Sebastian Stöhr",
17 | "pageTimings": {
18 | "onContentLoad": 3910,
19 | "onLoad": -1
20 | }
21 | }
22 | ],
23 | "entries": [
24 | {
25 | "pageref": "page_3",
26 | "startedDateTime": "NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN",
27 | "time": 3804,
28 | "request": {
29 | "method": "GET",
30 | "url": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css",
31 | "httpVersion": "HTTP/1.1",
32 | "cookies": [],
33 | "headers": [
34 | {
35 | "name": "Host",
36 | "value": "www.sebastianstoehr.de"
37 | },
38 | {
39 | "name": "User-Agent",
40 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
41 | },
42 | {
43 | "name": "Accept",
44 | "value": "text/css,*/*;q=0.1"
45 | },
46 | {
47 | "name": "Accept-Language",
48 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
49 | },
50 | {
51 | "name": "Accept-Encoding",
52 | "value": "gzip, deflate"
53 | },
54 | {
55 | "name": "DNT",
56 | "value": "1"
57 | },
58 | {
59 | "name": "Referer",
60 | "value": "http://www.sebastianstoehr.de/"
61 | },
62 | {
63 | "name": "Connection",
64 | "value": "keep-alive"
65 | }
66 | ],
67 | "queryString": [],
68 | "headersSize": 676,
69 | "bodySize": -1
70 | },
71 | "response": {
72 | "status": 200,
73 | "statusText": "OK",
74 | "httpVersion": "HTTP/1.1",
75 | "cookies": [],
76 | "headers": [
77 | {
78 | "name": "Date",
79 | "value": "Sun, 26 Jan 2014 17:37:44 GMT"
80 | },
81 | {
82 | "name": "Server",
83 | "value": "Apache"
84 | },
85 | {
86 | "name": "Last-Modified",
87 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
88 | },
89 | {
90 | "name": "Accept-Ranges",
91 | "value": "bytes"
92 | },
93 | {
94 | "name": "Content-Length",
95 | "value": "3412"
96 | },
97 | {
98 | "name": "Cache-Control",
99 | "value": "max-age=15552000"
100 | },
101 | {
102 | "name": "Expires",
103 | "value": "Fri, 25 Jul 2014 17:37:44 GMT"
104 | },
105 | {
106 | "name": "Vary",
107 | "value": "Accept-Encoding"
108 | },
109 | {
110 | "name": "Keep-Alive",
111 | "value": "timeout=2, max=200"
112 | },
113 | {
114 | "name": "Connection",
115 | "value": "Keep-Alive"
116 | },
117 | {
118 | "name": "Content-Type",
119 | "value": "text/css"
120 | },
121 | {
122 | "name": "Content-Encoding",
123 | "value": "gzip"
124 | }
125 | ],
126 | "content": {
127 | "mimeType": "text/css",
128 | "size": 12647,
129 | "text": "--- REMOVED ---\n"
130 | },
131 | "redirectURL": "",
132 | "headersSize": 362,
133 | "bodySize": 3412
134 | },
135 | "cache": {},
136 | "timings": {
137 | "blocked": 5,
138 | "dns": 0,
139 | "connect": 0,
140 | "send": 0,
141 | "wait": 3778,
142 | "receive": 21
143 | },
144 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
145 | "connection": "80"
146 | },
147 | {
148 | "pageref": "page_3",
149 | "startedDateTime": "NaN-NaN-NaNTNaN:NaN:NaN.NaN+NaN:NaN",
150 | "time": 9092,
151 | "request": {
152 | "method": "GET",
153 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg",
154 | "httpVersion": "HTTP/1.1",
155 | "cookies": [],
156 | "headers": [
157 | {
158 | "name": "Host",
159 | "value": "www.sebastianstoehr.de"
160 | },
161 | {
162 | "name": "User-Agent",
163 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
164 | },
165 | {
166 | "name": "Accept",
167 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
168 | },
169 | {
170 | "name": "Accept-Language",
171 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
172 | },
173 | {
174 | "name": "Accept-Encoding",
175 | "value": "gzip, deflate"
176 | },
177 | {
178 | "name": "DNT",
179 | "value": "1"
180 | },
181 | {
182 | "name": "Referer",
183 | "value": "http://www.sebastianstoehr.de/"
184 | },
185 | {
186 | "name": "Connection",
187 | "value": "keep-alive"
188 | }
189 | ],
190 | "queryString": [],
191 | "headersSize": 704,
192 | "bodySize": -1
193 | },
194 | "response": {
195 | "status": 200,
196 | "statusText": "OK",
197 | "httpVersion": "HTTP/1.1",
198 | "cookies": [],
199 | "headers": [
200 | {
201 | "name": "Date",
202 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
203 | },
204 | {
205 | "name": "Server",
206 | "value": "Apache"
207 | },
208 | {
209 | "name": "Last-Modified",
210 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
211 | },
212 | {
213 | "name": "Accept-Ranges",
214 | "value": "bytes"
215 | },
216 | {
217 | "name": "Content-Length",
218 | "value": "16997"
219 | },
220 | {
221 | "name": "Cache-Control",
222 | "value": "max-age=15552000"
223 | },
224 | {
225 | "name": "Expires",
226 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
227 | },
228 | {
229 | "name": "Keep-Alive",
230 | "value": "timeout=2, max=200"
231 | },
232 | {
233 | "name": "Connection",
234 | "value": "Keep-Alive"
235 | },
236 | {
237 | "name": "Content-Type",
238 | "value": "image/jpeg"
239 | }
240 | ],
241 | "content": {
242 | "mimeType": "image/jpeg",
243 | "size": 132,
244 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg"
245 | },
246 | "redirectURL": "",
247 | "headersSize": 318,
248 | "bodySize": 16997
249 | },
250 | "cache": {},
251 | "timings": {
252 | "blocked": 3804,
253 | "dns": 0,
254 | "connect": 0,
255 | "send": 0,
256 | "wait": 5209,
257 | "receive": 79
258 | },
259 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
260 | "connection": "80"
261 | },
262 | {
263 | "pageref": "page_3",
264 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
265 | "time": 9139,
266 | "request": {
267 | "method": "GET",
268 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg",
269 | "httpVersion": "HTTP/1.1",
270 | "cookies": [],
271 | "headers": [
272 | {
273 | "name": "Host",
274 | "value": "www.sebastianstoehr.de"
275 | },
276 | {
277 | "name": "User-Agent",
278 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
279 | },
280 | {
281 | "name": "Accept",
282 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
283 | },
284 | {
285 | "name": "Accept-Language",
286 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
287 | },
288 | {
289 | "name": "Accept-Encoding",
290 | "value": "gzip, deflate"
291 | },
292 | {
293 | "name": "DNT",
294 | "value": "1"
295 | },
296 | {
297 | "name": "Referer",
298 | "value": "http://www.sebastianstoehr.de/"
299 | },
300 | {
301 | "name": "Connection",
302 | "value": "keep-alive"
303 | }
304 | ],
305 | "queryString": [],
306 | "headersSize": 707,
307 | "bodySize": -1
308 | },
309 | "response": {
310 | "status": 200,
311 | "statusText": "OK",
312 | "httpVersion": "HTTP/1.1",
313 | "cookies": [],
314 | "headers": [
315 | {
316 | "name": "Date",
317 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
318 | },
319 | {
320 | "name": "Server",
321 | "value": "Apache"
322 | },
323 | {
324 | "name": "Last-Modified",
325 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
326 | },
327 | {
328 | "name": "Accept-Ranges",
329 | "value": "bytes"
330 | },
331 | {
332 | "name": "Content-Length",
333 | "value": "28351"
334 | },
335 | {
336 | "name": "Cache-Control",
337 | "value": "max-age=15552000"
338 | },
339 | {
340 | "name": "Expires",
341 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
342 | },
343 | {
344 | "name": "Keep-Alive",
345 | "value": "timeout=2, max=200"
346 | },
347 | {
348 | "name": "Connection",
349 | "value": "Keep-Alive"
350 | },
351 | {
352 | "name": "Content-Type",
353 | "value": "image/jpeg"
354 | }
355 | ],
356 | "content": {
357 | "mimeType": "image/jpeg",
358 | "size": 135,
359 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg"
360 | },
361 | "redirectURL": "",
362 | "headersSize": 318,
363 | "bodySize": 28351
364 | },
365 | "cache": {},
366 | "timings": {
367 | "blocked": 3804,
368 | "dns": 0,
369 | "connect": 0,
370 | "send": 0,
371 | "wait": 5240,
372 | "receive": 95
373 | },
374 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
375 | "connection": "80"
376 | },
377 | {
378 | "pageref": "page_3",
379 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
380 | "time": 9164,
381 | "request": {
382 | "method": "GET",
383 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg",
384 | "httpVersion": "HTTP/1.1",
385 | "cookies": [],
386 | "headers": [
387 | {
388 | "name": "Host",
389 | "value": "www.sebastianstoehr.de"
390 | },
391 | {
392 | "name": "User-Agent",
393 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
394 | },
395 | {
396 | "name": "Accept",
397 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
398 | },
399 | {
400 | "name": "Accept-Language",
401 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
402 | },
403 | {
404 | "name": "Accept-Encoding",
405 | "value": "gzip, deflate"
406 | },
407 | {
408 | "name": "DNT",
409 | "value": "1"
410 | },
411 | {
412 | "name": "Referer",
413 | "value": "http://www.sebastianstoehr.de/"
414 | },
415 | {
416 | "name": "Connection",
417 | "value": "keep-alive"
418 | }
419 | ],
420 | "queryString": [],
421 | "headersSize": 701,
422 | "bodySize": -1
423 | },
424 | "response": {
425 | "status": 200,
426 | "statusText": "OK",
427 | "httpVersion": "HTTP/1.1",
428 | "cookies": [],
429 | "headers": [
430 | {
431 | "name": "Date",
432 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
433 | },
434 | {
435 | "name": "Server",
436 | "value": "Apache"
437 | },
438 | {
439 | "name": "Last-Modified",
440 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
441 | },
442 | {
443 | "name": "Accept-Ranges",
444 | "value": "bytes"
445 | },
446 | {
447 | "name": "Content-Length",
448 | "value": "73064"
449 | },
450 | {
451 | "name": "Cache-Control",
452 | "value": "max-age=15552000"
453 | },
454 | {
455 | "name": "Expires",
456 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
457 | },
458 | {
459 | "name": "Keep-Alive",
460 | "value": "timeout=2, max=200"
461 | },
462 | {
463 | "name": "Connection",
464 | "value": "Keep-Alive"
465 | },
466 | {
467 | "name": "Content-Type",
468 | "value": "image/jpeg"
469 | }
470 | ],
471 | "content": {
472 | "mimeType": "image/jpeg",
473 | "size": 129,
474 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg"
475 | },
476 | "redirectURL": "",
477 | "headersSize": 318,
478 | "bodySize": 73064
479 | },
480 | "cache": {},
481 | "timings": {
482 | "blocked": 3804,
483 | "dns": 0,
484 | "connect": 0,
485 | "send": 0,
486 | "wait": 5217,
487 | "receive": 143
488 | },
489 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
490 | "connection": "80"
491 | },
492 | {
493 | "pageref": "page_3",
494 | "startedDateTime": "2014-01-26T18:37:43.814+01:00",
495 | "time": 9156,
496 | "request": {
497 | "method": "GET",
498 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg",
499 | "httpVersion": "HTTP/1.1",
500 | "cookies": [],
501 | "headers": [
502 | {
503 | "name": "Host",
504 | "value": "www.sebastianstoehr.de"
505 | },
506 | {
507 | "name": "User-Agent",
508 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
509 | },
510 | {
511 | "name": "Accept",
512 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
513 | },
514 | {
515 | "name": "Accept-Language",
516 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
517 | },
518 | {
519 | "name": "Accept-Encoding",
520 | "value": "gzip, deflate"
521 | },
522 | {
523 | "name": "DNT",
524 | "value": "1"
525 | },
526 | {
527 | "name": "Referer",
528 | "value": "http://www.sebastianstoehr.de/"
529 | },
530 | {
531 | "name": "Connection",
532 | "value": "keep-alive"
533 | }
534 | ],
535 | "queryString": [],
536 | "headersSize": 705,
537 | "bodySize": -1
538 | },
539 | "response": {
540 | "status": 200,
541 | "statusText": "OK",
542 | "httpVersion": "HTTP/1.1",
543 | "cookies": [],
544 | "headers": [
545 | {
546 | "name": "Date",
547 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
548 | },
549 | {
550 | "name": "Server",
551 | "value": "Apache"
552 | },
553 | {
554 | "name": "Last-Modified",
555 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
556 | },
557 | {
558 | "name": "Accept-Ranges",
559 | "value": "bytes"
560 | },
561 | {
562 | "name": "Content-Length",
563 | "value": "49555"
564 | },
565 | {
566 | "name": "Cache-Control",
567 | "value": "max-age=15552000"
568 | },
569 | {
570 | "name": "Expires",
571 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
572 | },
573 | {
574 | "name": "Keep-Alive",
575 | "value": "timeout=2, max=200"
576 | },
577 | {
578 | "name": "Connection",
579 | "value": "Keep-Alive"
580 | },
581 | {
582 | "name": "Content-Type",
583 | "value": "image/jpeg"
584 | }
585 | ],
586 | "content": {
587 | "mimeType": "image/jpeg",
588 | "size": 133,
589 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg"
590 | },
591 | "redirectURL": "",
592 | "headersSize": 318,
593 | "bodySize": 49555
594 | },
595 | "cache": {},
596 | "timings": {
597 | "blocked": 3803,
598 | "dns": 0,
599 | "connect": 0,
600 | "send": 0,
601 | "wait": 5222,
602 | "receive": 131
603 | },
604 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
605 | "connection": "80"
606 | },
607 | {
608 | "pageref": "page_3",
609 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
610 | "time": 5010,
611 | "request": {
612 | "method": "GET",
613 | "url": "http://www.sebastianstoehr.de/res/images/logo.png",
614 | "httpVersion": "HTTP/1.1",
615 | "cookies": [],
616 | "headers": [
617 | {
618 | "name": "Host",
619 | "value": "www.sebastianstoehr.de"
620 | },
621 | {
622 | "name": "User-Agent",
623 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
624 | },
625 | {
626 | "name": "Accept",
627 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
628 | },
629 | {
630 | "name": "Accept-Language",
631 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
632 | },
633 | {
634 | "name": "Accept-Encoding",
635 | "value": "gzip, deflate"
636 | },
637 | {
638 | "name": "DNT",
639 | "value": "1"
640 | },
641 | {
642 | "name": "Referer",
643 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
644 | },
645 | {
646 | "name": "Connection",
647 | "value": "keep-alive"
648 | }
649 | ],
650 | "queryString": [],
651 | "headersSize": 710,
652 | "bodySize": -1
653 | },
654 | "response": {
655 | "status": 200,
656 | "statusText": "OK",
657 | "httpVersion": "HTTP/1.1",
658 | "cookies": [],
659 | "headers": [
660 | {
661 | "name": "Date",
662 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
663 | },
664 | {
665 | "name": "Server",
666 | "value": "Apache"
667 | },
668 | {
669 | "name": "Last-Modified",
670 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
671 | },
672 | {
673 | "name": "Accept-Ranges",
674 | "value": "bytes"
675 | },
676 | {
677 | "name": "Content-Length",
678 | "value": "717"
679 | },
680 | {
681 | "name": "Cache-Control",
682 | "value": "max-age=15552000"
683 | },
684 | {
685 | "name": "Expires",
686 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
687 | },
688 | {
689 | "name": "Keep-Alive",
690 | "value": "timeout=2, max=199"
691 | },
692 | {
693 | "name": "Connection",
694 | "value": "Keep-Alive"
695 | },
696 | {
697 | "name": "Content-Type",
698 | "value": "image/png"
699 | }
700 | ],
701 | "content": {
702 | "mimeType": "image/png",
703 | "size": 91,
704 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/logo.png"
705 | },
706 | "redirectURL": "",
707 | "headersSize": 315,
708 | "bodySize": 717
709 | },
710 | "cache": {},
711 | "timings": {
712 | "blocked": 0,
713 | "dns": 0,
714 | "connect": 0,
715 | "send": 0,
716 | "wait": 5010,
717 | "receive": 0
718 | },
719 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
720 | "connection": "80"
721 | },
722 | {
723 | "pageref": "page_3",
724 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
725 | "time": 5032,
726 | "request": {
727 | "method": "GET",
728 | "url": "http://www.sebastianstoehr.de/res/images/socialbar.png",
729 | "httpVersion": "HTTP/1.1",
730 | "cookies": [],
731 | "headers": [
732 | {
733 | "name": "Host",
734 | "value": "www.sebastianstoehr.de"
735 | },
736 | {
737 | "name": "User-Agent",
738 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
739 | },
740 | {
741 | "name": "Accept",
742 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
743 | },
744 | {
745 | "name": "Accept-Language",
746 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
747 | },
748 | {
749 | "name": "Accept-Encoding",
750 | "value": "gzip, deflate"
751 | },
752 | {
753 | "name": "DNT",
754 | "value": "1"
755 | },
756 | {
757 | "name": "Referer",
758 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
759 | },
760 | {
761 | "name": "Connection",
762 | "value": "keep-alive"
763 | }
764 | ],
765 | "queryString": [],
766 | "headersSize": 715,
767 | "bodySize": -1
768 | },
769 | "response": {
770 | "status": 200,
771 | "statusText": "OK",
772 | "httpVersion": "HTTP/1.1",
773 | "cookies": [],
774 | "headers": [
775 | {
776 | "name": "Date",
777 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
778 | },
779 | {
780 | "name": "Server",
781 | "value": "Apache"
782 | },
783 | {
784 | "name": "Last-Modified",
785 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
786 | },
787 | {
788 | "name": "Accept-Ranges",
789 | "value": "bytes"
790 | },
791 | {
792 | "name": "Content-Length",
793 | "value": "2772"
794 | },
795 | {
796 | "name": "Cache-Control",
797 | "value": "max-age=15552000"
798 | },
799 | {
800 | "name": "Expires",
801 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
802 | },
803 | {
804 | "name": "Keep-Alive",
805 | "value": "timeout=2, max=200"
806 | },
807 | {
808 | "name": "Connection",
809 | "value": "Keep-Alive"
810 | },
811 | {
812 | "name": "Content-Type",
813 | "value": "image/png"
814 | }
815 | ],
816 | "content": {
817 | "mimeType": "image/png",
818 | "size": 96,
819 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/socialbar.png"
820 | },
821 | "redirectURL": "",
822 | "headersSize": 316,
823 | "bodySize": 2772
824 | },
825 | "cache": {},
826 | "timings": {
827 | "blocked": 0,
828 | "dns": 0,
829 | "connect": 29,
830 | "send": 0,
831 | "wait": 4980,
832 | "receive": 23
833 | },
834 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
835 | "connection": "80"
836 | },
837 | {
838 | "pageref": "page_3",
839 | "startedDateTime": "2014-01-26T18:37:47.711+01:00",
840 | "time": 5057,
841 | "request": {
842 | "method": "GET",
843 | "url": "http://www.sebastianstoehr.de/assets/app-d6d60b5cc834e6a9ce6fbfee22da998f.js",
844 | "httpVersion": "HTTP/1.1",
845 | "cookies": [],
846 | "headers": [
847 | {
848 | "name": "Host",
849 | "value": "www.sebastianstoehr.de"
850 | },
851 | {
852 | "name": "User-Agent",
853 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
854 | },
855 | {
856 | "name": "Accept",
857 | "value": "*/*"
858 | },
859 | {
860 | "name": "Accept-Language",
861 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
862 | },
863 | {
864 | "name": "Accept-Encoding",
865 | "value": "gzip, deflate"
866 | },
867 | {
868 | "name": "DNT",
869 | "value": "1"
870 | },
871 | {
872 | "name": "Referer",
873 | "value": "http://www.sebastianstoehr.de/"
874 | },
875 | {
876 | "name": "Connection",
877 | "value": "keep-alive"
878 | }
879 | ],
880 | "queryString": [],
881 | "headersSize": 660,
882 | "bodySize": -1
883 | },
884 | "response": {
885 | "status": 200,
886 | "statusText": "OK",
887 | "httpVersion": "HTTP/1.1",
888 | "cookies": [],
889 | "headers": [
890 | {
891 | "name": "Date",
892 | "value": "Sun, 26 Jan 2014 17:37:53 GMT"
893 | },
894 | {
895 | "name": "Server",
896 | "value": "Apache"
897 | },
898 | {
899 | "name": "Last-Modified",
900 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
901 | },
902 | {
903 | "name": "Accept-Ranges",
904 | "value": "bytes"
905 | },
906 | {
907 | "name": "Content-Length",
908 | "value": "4453"
909 | },
910 | {
911 | "name": "Cache-Control",
912 | "value": "max-age=15552000"
913 | },
914 | {
915 | "name": "Expires",
916 | "value": "Fri, 25 Jul 2014 17:37:53 GMT"
917 | },
918 | {
919 | "name": "Vary",
920 | "value": "Accept-Encoding"
921 | },
922 | {
923 | "name": "Keep-Alive",
924 | "value": "timeout=2, max=198"
925 | },
926 | {
927 | "name": "Connection",
928 | "value": "Keep-Alive"
929 | },
930 | {
931 | "name": "Content-Type",
932 | "value": "text/javascript"
933 | },
934 | {
935 | "name": "Content-Encoding",
936 | "value": "gzip"
937 | }
938 | ],
939 | "content": {
940 | "mimeType": "text/javascript",
941 | "size": 11676,
942 | "text": "--- REMOVED ---\n"
943 | },
944 | "redirectURL": "",
945 | "headersSize": 369,
946 | "bodySize": 4453
947 | },
948 | "cache": {},
949 | "timings": {
950 | "blocked": 5000,
951 | "dns": 0,
952 | "connect": 0,
953 | "send": 0,
954 | "wait": 55,
955 | "receive": 2
956 | },
957 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
958 | "connection": "80"
959 | }
960 | ]
961 | }
962 | }
--------------------------------------------------------------------------------
/src/test/resources/sstoehr.invalid-integer.har:
--------------------------------------------------------------------------------
1 | {
2 | "log": {
3 | "version": "1.1",
4 | "creator": {
5 | "name": "Firebug",
6 | "version": "1.12"
7 | },
8 | "browser": {
9 | "name": "Firefox",
10 | "version": "26.0"
11 | },
12 | "pages": [
13 | {
14 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
15 | "id": "page_3",
16 | "title": "Home — Sebastian Stöhr",
17 | "pageTimings": {
18 | "onContentLoad": 3910,
19 | "onLoad": -1
20 | }
21 | }
22 | ],
23 | "entries": [
24 | {
25 | "pageref": "page_3",
26 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
27 | "time": 3804,
28 | "request": {
29 | "method": "GET",
30 | "url": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css",
31 | "httpVersion": "HTTP/1.1",
32 | "cookies": [],
33 | "headers": [
34 | {
35 | "name": "Host",
36 | "value": "www.sebastianstoehr.de"
37 | },
38 | {
39 | "name": "User-Agent",
40 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
41 | },
42 | {
43 | "name": "Accept",
44 | "value": "text/css,*/*;q=0.1"
45 | },
46 | {
47 | "name": "Accept-Language",
48 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
49 | },
50 | {
51 | "name": "Accept-Encoding",
52 | "value": "gzip, deflate"
53 | },
54 | {
55 | "name": "DNT",
56 | "value": "1"
57 | },
58 | {
59 | "name": "Referer",
60 | "value": "http://www.sebastianstoehr.de/"
61 | },
62 | {
63 | "name": "Connection",
64 | "value": "keep-alive"
65 | }
66 | ],
67 | "queryString": [],
68 | "headersSize": 676,
69 | "bodySize": -1
70 | },
71 | "response": {
72 | "status": 200,
73 | "statusText": "OK",
74 | "httpVersion": "HTTP/1.1",
75 | "cookies": [],
76 | "headers": [
77 | {
78 | "name": "Date",
79 | "value": "Sun, 26 Jan 2014 17:37:44 GMT"
80 | },
81 | {
82 | "name": "Server",
83 | "value": "Apache"
84 | },
85 | {
86 | "name": "Last-Modified",
87 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
88 | },
89 | {
90 | "name": "Accept-Ranges",
91 | "value": "bytes"
92 | },
93 | {
94 | "name": "Content-Length",
95 | "value": "3412"
96 | },
97 | {
98 | "name": "Cache-Control",
99 | "value": "max-age=15552000"
100 | },
101 | {
102 | "name": "Expires",
103 | "value": "Fri, 25 Jul 2014 17:37:44 GMT"
104 | },
105 | {
106 | "name": "Vary",
107 | "value": "Accept-Encoding"
108 | },
109 | {
110 | "name": "Keep-Alive",
111 | "value": "timeout=2, max=200"
112 | },
113 | {
114 | "name": "Connection",
115 | "value": "Keep-Alive"
116 | },
117 | {
118 | "name": "Content-Type",
119 | "value": "text/css"
120 | },
121 | {
122 | "name": "Content-Encoding",
123 | "value": "gzip"
124 | }
125 | ],
126 | "content": {
127 | "mimeType": "text/css",
128 | "size": 12647,
129 | "text": "--- REMOVED ---\n"
130 | },
131 | "redirectURL": "",
132 | "headersSize": 362,
133 | "bodySize": 3412
134 | },
135 | "cache": {},
136 | "timings": {
137 | "blocked": 5,
138 | "dns": 0,
139 | "connect": 0,
140 | "send": 0,
141 | "wait": 3778,
142 | "receive": 63596250212317
143 | },
144 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
145 | "connection": "80"
146 | },
147 | {
148 | "pageref": "page_3",
149 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
150 | "time": 9092,
151 | "request": {
152 | "method": "GET",
153 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg",
154 | "httpVersion": "HTTP/1.1",
155 | "cookies": [],
156 | "headers": [
157 | {
158 | "name": "Host",
159 | "value": "www.sebastianstoehr.de"
160 | },
161 | {
162 | "name": "User-Agent",
163 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
164 | },
165 | {
166 | "name": "Accept",
167 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
168 | },
169 | {
170 | "name": "Accept-Language",
171 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
172 | },
173 | {
174 | "name": "Accept-Encoding",
175 | "value": "gzip, deflate"
176 | },
177 | {
178 | "name": "DNT",
179 | "value": "1"
180 | },
181 | {
182 | "name": "Referer",
183 | "value": "http://www.sebastianstoehr.de/"
184 | },
185 | {
186 | "name": "Connection",
187 | "value": "keep-alive"
188 | }
189 | ],
190 | "queryString": [],
191 | "headersSize": 704,
192 | "bodySize": -1
193 | },
194 | "response": {
195 | "status": 200,
196 | "statusText": "OK",
197 | "httpVersion": "HTTP/1.1",
198 | "cookies": [],
199 | "headers": [
200 | {
201 | "name": "Date",
202 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
203 | },
204 | {
205 | "name": "Server",
206 | "value": "Apache"
207 | },
208 | {
209 | "name": "Last-Modified",
210 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
211 | },
212 | {
213 | "name": "Accept-Ranges",
214 | "value": "bytes"
215 | },
216 | {
217 | "name": "Content-Length",
218 | "value": "16997"
219 | },
220 | {
221 | "name": "Cache-Control",
222 | "value": "max-age=15552000"
223 | },
224 | {
225 | "name": "Expires",
226 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
227 | },
228 | {
229 | "name": "Keep-Alive",
230 | "value": "timeout=2, max=200"
231 | },
232 | {
233 | "name": "Connection",
234 | "value": "Keep-Alive"
235 | },
236 | {
237 | "name": "Content-Type",
238 | "value": "image/jpeg"
239 | }
240 | ],
241 | "content": {
242 | "mimeType": "image/jpeg",
243 | "size": 132,
244 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/woeste-alumni/header-600x131-bf1788.jpg"
245 | },
246 | "redirectURL": "",
247 | "headersSize": 318,
248 | "bodySize": 16997
249 | },
250 | "cache": {},
251 | "timings": {
252 | "blocked": 3804,
253 | "dns": 0,
254 | "connect": 0,
255 | "send": 0,
256 | "wait": 5209,
257 | "receive": 79
258 | },
259 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
260 | "connection": "80"
261 | },
262 | {
263 | "pageref": "page_3",
264 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
265 | "time": 9139,
266 | "request": {
267 | "method": "GET",
268 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg",
269 | "httpVersion": "HTTP/1.1",
270 | "cookies": [],
271 | "headers": [
272 | {
273 | "name": "Host",
274 | "value": "www.sebastianstoehr.de"
275 | },
276 | {
277 | "name": "User-Agent",
278 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
279 | },
280 | {
281 | "name": "Accept",
282 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
283 | },
284 | {
285 | "name": "Accept-Language",
286 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
287 | },
288 | {
289 | "name": "Accept-Encoding",
290 | "value": "gzip, deflate"
291 | },
292 | {
293 | "name": "DNT",
294 | "value": "1"
295 | },
296 | {
297 | "name": "Referer",
298 | "value": "http://www.sebastianstoehr.de/"
299 | },
300 | {
301 | "name": "Connection",
302 | "value": "keep-alive"
303 | }
304 | ],
305 | "queryString": [],
306 | "headersSize": 707,
307 | "bodySize": -1
308 | },
309 | "response": {
310 | "status": 200,
311 | "statusText": "OK",
312 | "httpVersion": "HTTP/1.1",
313 | "cookies": [],
314 | "headers": [
315 | {
316 | "name": "Date",
317 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
318 | },
319 | {
320 | "name": "Server",
321 | "value": "Apache"
322 | },
323 | {
324 | "name": "Last-Modified",
325 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
326 | },
327 | {
328 | "name": "Accept-Ranges",
329 | "value": "bytes"
330 | },
331 | {
332 | "name": "Content-Length",
333 | "value": "28351"
334 | },
335 | {
336 | "name": "Cache-Control",
337 | "value": "max-age=15552000"
338 | },
339 | {
340 | "name": "Expires",
341 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
342 | },
343 | {
344 | "name": "Keep-Alive",
345 | "value": "timeout=2, max=200"
346 | },
347 | {
348 | "name": "Connection",
349 | "value": "Keep-Alive"
350 | },
351 | {
352 | "name": "Content-Type",
353 | "value": "image/jpeg"
354 | }
355 | ],
356 | "content": {
357 | "mimeType": "image/jpeg",
358 | "size": 135,
359 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/sebastian-stoehr/header-600x131-415442.jpg"
360 | },
361 | "redirectURL": "",
362 | "headersSize": 318,
363 | "bodySize": 28351
364 | },
365 | "cache": {},
366 | "timings": {
367 | "blocked": 3804,
368 | "dns": 0,
369 | "connect": 0,
370 | "send": 0,
371 | "wait": 5240,
372 | "receive": 95
373 | },
374 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
375 | "connection": "80"
376 | },
377 | {
378 | "pageref": "page_3",
379 | "startedDateTime": "2014-01-26T18:37:43.813+01:00",
380 | "time": 9164,
381 | "request": {
382 | "method": "GET",
383 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg",
384 | "httpVersion": "HTTP/1.1",
385 | "cookies": [],
386 | "headers": [
387 | {
388 | "name": "Host",
389 | "value": "www.sebastianstoehr.de"
390 | },
391 | {
392 | "name": "User-Agent",
393 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
394 | },
395 | {
396 | "name": "Accept",
397 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
398 | },
399 | {
400 | "name": "Accept-Language",
401 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
402 | },
403 | {
404 | "name": "Accept-Encoding",
405 | "value": "gzip, deflate"
406 | },
407 | {
408 | "name": "DNT",
409 | "value": "1"
410 | },
411 | {
412 | "name": "Referer",
413 | "value": "http://www.sebastianstoehr.de/"
414 | },
415 | {
416 | "name": "Connection",
417 | "value": "keep-alive"
418 | }
419 | ],
420 | "queryString": [],
421 | "headersSize": 701,
422 | "bodySize": -1
423 | },
424 | "response": {
425 | "status": 200,
426 | "statusText": "OK",
427 | "httpVersion": "HTTP/1.1",
428 | "cookies": [],
429 | "headers": [
430 | {
431 | "name": "Date",
432 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
433 | },
434 | {
435 | "name": "Server",
436 | "value": "Apache"
437 | },
438 | {
439 | "name": "Last-Modified",
440 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
441 | },
442 | {
443 | "name": "Accept-Ranges",
444 | "value": "bytes"
445 | },
446 | {
447 | "name": "Content-Length",
448 | "value": "73064"
449 | },
450 | {
451 | "name": "Cache-Control",
452 | "value": "max-age=15552000"
453 | },
454 | {
455 | "name": "Expires",
456 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
457 | },
458 | {
459 | "name": "Keep-Alive",
460 | "value": "timeout=2, max=200"
461 | },
462 | {
463 | "name": "Connection",
464 | "value": "Keep-Alive"
465 | },
466 | {
467 | "name": "Content-Type",
468 | "value": "image/jpeg"
469 | }
470 | ],
471 | "content": {
472 | "mimeType": "image/jpeg",
473 | "size": 129,
474 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/abizeitung/header-600x131-603283.jpg"
475 | },
476 | "redirectURL": "",
477 | "headersSize": 318,
478 | "bodySize": 73064
479 | },
480 | "cache": {},
481 | "timings": {
482 | "blocked": 3804,
483 | "dns": 0,
484 | "connect": 0,
485 | "send": 0,
486 | "wait": 5217,
487 | "receive": 143
488 | },
489 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
490 | "connection": "80"
491 | },
492 | {
493 | "pageref": "page_3",
494 | "startedDateTime": "2014-01-26T18:37:43.814+01:00",
495 | "time": 9156,
496 | "request": {
497 | "method": "GET",
498 | "url": "http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg",
499 | "httpVersion": "HTTP/1.1",
500 | "cookies": [],
501 | "headers": [
502 | {
503 | "name": "Host",
504 | "value": "www.sebastianstoehr.de"
505 | },
506 | {
507 | "name": "User-Agent",
508 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
509 | },
510 | {
511 | "name": "Accept",
512 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
513 | },
514 | {
515 | "name": "Accept-Language",
516 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
517 | },
518 | {
519 | "name": "Accept-Encoding",
520 | "value": "gzip, deflate"
521 | },
522 | {
523 | "name": "DNT",
524 | "value": "1"
525 | },
526 | {
527 | "name": "Referer",
528 | "value": "http://www.sebastianstoehr.de/"
529 | },
530 | {
531 | "name": "Connection",
532 | "value": "keep-alive"
533 | }
534 | ],
535 | "queryString": [],
536 | "headersSize": 705,
537 | "bodySize": -1
538 | },
539 | "response": {
540 | "status": 200,
541 | "statusText": "OK",
542 | "httpVersion": "HTTP/1.1",
543 | "cookies": [],
544 | "headers": [
545 | {
546 | "name": "Date",
547 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
548 | },
549 | {
550 | "name": "Server",
551 | "value": "Apache"
552 | },
553 | {
554 | "name": "Last-Modified",
555 | "value": "Sat, 11 Jan 2014 10:56:50 GMT"
556 | },
557 | {
558 | "name": "Accept-Ranges",
559 | "value": "bytes"
560 | },
561 | {
562 | "name": "Content-Length",
563 | "value": "49555"
564 | },
565 | {
566 | "name": "Cache-Control",
567 | "value": "max-age=15552000"
568 | },
569 | {
570 | "name": "Expires",
571 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
572 | },
573 | {
574 | "name": "Keep-Alive",
575 | "value": "timeout=2, max=200"
576 | },
577 | {
578 | "name": "Connection",
579 | "value": "Keep-Alive"
580 | },
581 | {
582 | "name": "Content-Type",
583 | "value": "image/jpeg"
584 | }
585 | ],
586 | "content": {
587 | "mimeType": "image/jpeg",
588 | "size": 133,
589 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/portfolio/junge-liberale/header-600x131-a069fc.jpg"
590 | },
591 | "redirectURL": "",
592 | "headersSize": 318,
593 | "bodySize": 49555
594 | },
595 | "cache": {},
596 | "timings": {
597 | "blocked": 3803,
598 | "dns": 0,
599 | "connect": 0,
600 | "send": 0,
601 | "wait": 5222,
602 | "receive": 131
603 | },
604 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
605 | "connection": "80"
606 | },
607 | {
608 | "pageref": "page_3",
609 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
610 | "time": 5010,
611 | "request": {
612 | "method": "GET",
613 | "url": "http://www.sebastianstoehr.de/res/images/logo.png",
614 | "httpVersion": "HTTP/1.1",
615 | "cookies": [],
616 | "headers": [
617 | {
618 | "name": "Host",
619 | "value": "www.sebastianstoehr.de"
620 | },
621 | {
622 | "name": "User-Agent",
623 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
624 | },
625 | {
626 | "name": "Accept",
627 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
628 | },
629 | {
630 | "name": "Accept-Language",
631 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
632 | },
633 | {
634 | "name": "Accept-Encoding",
635 | "value": "gzip, deflate"
636 | },
637 | {
638 | "name": "DNT",
639 | "value": "1"
640 | },
641 | {
642 | "name": "Referer",
643 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
644 | },
645 | {
646 | "name": "Connection",
647 | "value": "keep-alive"
648 | }
649 | ],
650 | "queryString": [],
651 | "headersSize": 710,
652 | "bodySize": -1
653 | },
654 | "response": {
655 | "status": 200,
656 | "statusText": "OK",
657 | "httpVersion": "HTTP/1.1",
658 | "cookies": [],
659 | "headers": [
660 | {
661 | "name": "Date",
662 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
663 | },
664 | {
665 | "name": "Server",
666 | "value": "Apache"
667 | },
668 | {
669 | "name": "Last-Modified",
670 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
671 | },
672 | {
673 | "name": "Accept-Ranges",
674 | "value": "bytes"
675 | },
676 | {
677 | "name": "Content-Length",
678 | "value": "717"
679 | },
680 | {
681 | "name": "Cache-Control",
682 | "value": "max-age=15552000"
683 | },
684 | {
685 | "name": "Expires",
686 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
687 | },
688 | {
689 | "name": "Keep-Alive",
690 | "value": "timeout=2, max=199"
691 | },
692 | {
693 | "name": "Connection",
694 | "value": "Keep-Alive"
695 | },
696 | {
697 | "name": "Content-Type",
698 | "value": "image/png"
699 | }
700 | ],
701 | "content": {
702 | "mimeType": "image/png",
703 | "size": 91,
704 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/logo.png"
705 | },
706 | "redirectURL": "",
707 | "headersSize": 315,
708 | "bodySize": 717
709 | },
710 | "cache": {},
711 | "timings": {
712 | "blocked": 0,
713 | "dns": 0,
714 | "connect": 0,
715 | "send": 0,
716 | "wait": 5010,
717 | "receive": 0
718 | },
719 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
720 | "connection": "80"
721 | },
722 | {
723 | "pageref": "page_3",
724 | "startedDateTime": "2014-01-26T18:37:47.701+01:00",
725 | "time": 5032,
726 | "request": {
727 | "method": "GET",
728 | "url": "http://www.sebastianstoehr.de/res/images/socialbar.png",
729 | "httpVersion": "HTTP/1.1",
730 | "cookies": [],
731 | "headers": [
732 | {
733 | "name": "Host",
734 | "value": "www.sebastianstoehr.de"
735 | },
736 | {
737 | "name": "User-Agent",
738 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
739 | },
740 | {
741 | "name": "Accept",
742 | "value": "image/png,image/*;q=0.8,*/*;q=0.5"
743 | },
744 | {
745 | "name": "Accept-Language",
746 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
747 | },
748 | {
749 | "name": "Accept-Encoding",
750 | "value": "gzip, deflate"
751 | },
752 | {
753 | "name": "DNT",
754 | "value": "1"
755 | },
756 | {
757 | "name": "Referer",
758 | "value": "http://www.sebastianstoehr.de/assets/app-176c7b354c124a4593b8d4ac674d69e6.css"
759 | },
760 | {
761 | "name": "Connection",
762 | "value": "keep-alive"
763 | }
764 | ],
765 | "queryString": [],
766 | "headersSize": 715,
767 | "bodySize": -1
768 | },
769 | "response": {
770 | "status": 200,
771 | "statusText": "OK",
772 | "httpVersion": "HTTP/1.1",
773 | "cookies": [],
774 | "headers": [
775 | {
776 | "name": "Date",
777 | "value": "Sun, 26 Jan 2014 17:37:48 GMT"
778 | },
779 | {
780 | "name": "Server",
781 | "value": "Apache"
782 | },
783 | {
784 | "name": "Last-Modified",
785 | "value": "Sat, 11 Jan 2014 10:56:55 GMT"
786 | },
787 | {
788 | "name": "Accept-Ranges",
789 | "value": "bytes"
790 | },
791 | {
792 | "name": "Content-Length",
793 | "value": "2772"
794 | },
795 | {
796 | "name": "Cache-Control",
797 | "value": "max-age=15552000"
798 | },
799 | {
800 | "name": "Expires",
801 | "value": "Fri, 25 Jul 2014 17:37:48 GMT"
802 | },
803 | {
804 | "name": "Keep-Alive",
805 | "value": "timeout=2, max=200"
806 | },
807 | {
808 | "name": "Connection",
809 | "value": "Keep-Alive"
810 | },
811 | {
812 | "name": "Content-Type",
813 | "value": "image/png"
814 | }
815 | ],
816 | "content": {
817 | "mimeType": "image/png",
818 | "size": 96,
819 | "text": "Die Quelle von diesem URL ist kein Text:: http://www.sebastianstoehr.de/res/images/socialbar.png"
820 | },
821 | "redirectURL": "",
822 | "headersSize": 316,
823 | "bodySize": 2772
824 | },
825 | "cache": {},
826 | "timings": {
827 | "blocked": 0,
828 | "dns": 0,
829 | "connect": 29,
830 | "send": 0,
831 | "wait": 4980,
832 | "receive": 23
833 | },
834 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
835 | "connection": "80"
836 | },
837 | {
838 | "pageref": "page_3",
839 | "startedDateTime": "2014-01-26T18:37:47.711+01:00",
840 | "time": 5057,
841 | "request": {
842 | "method": "GET",
843 | "url": "http://www.sebastianstoehr.de/assets/app-d6d60b5cc834e6a9ce6fbfee22da998f.js",
844 | "httpVersion": "HTTP/1.1",
845 | "cookies": [],
846 | "headers": [
847 | {
848 | "name": "Host",
849 | "value": "www.sebastianstoehr.de"
850 | },
851 | {
852 | "name": "User-Agent",
853 | "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0"
854 | },
855 | {
856 | "name": "Accept",
857 | "value": "*/*"
858 | },
859 | {
860 | "name": "Accept-Language",
861 | "value": "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
862 | },
863 | {
864 | "name": "Accept-Encoding",
865 | "value": "gzip, deflate"
866 | },
867 | {
868 | "name": "DNT",
869 | "value": "1"
870 | },
871 | {
872 | "name": "Referer",
873 | "value": "http://www.sebastianstoehr.de/"
874 | },
875 | {
876 | "name": "Connection",
877 | "value": "keep-alive"
878 | }
879 | ],
880 | "queryString": [],
881 | "headersSize": 660,
882 | "bodySize": -1
883 | },
884 | "response": {
885 | "status": 200,
886 | "statusText": "OK",
887 | "httpVersion": "HTTP/1.1",
888 | "cookies": [],
889 | "headers": [
890 | {
891 | "name": "Date",
892 | "value": "Sun, 26 Jan 2014 17:37:53 GMT"
893 | },
894 | {
895 | "name": "Server",
896 | "value": "Apache"
897 | },
898 | {
899 | "name": "Last-Modified",
900 | "value": "Fri, 10 Jan 2014 17:10:50 GMT"
901 | },
902 | {
903 | "name": "Accept-Ranges",
904 | "value": "bytes"
905 | },
906 | {
907 | "name": "Content-Length",
908 | "value": "4453"
909 | },
910 | {
911 | "name": "Cache-Control",
912 | "value": "max-age=15552000"
913 | },
914 | {
915 | "name": "Expires",
916 | "value": "Fri, 25 Jul 2014 17:37:53 GMT"
917 | },
918 | {
919 | "name": "Vary",
920 | "value": "Accept-Encoding"
921 | },
922 | {
923 | "name": "Keep-Alive",
924 | "value": "timeout=2, max=198"
925 | },
926 | {
927 | "name": "Connection",
928 | "value": "Keep-Alive"
929 | },
930 | {
931 | "name": "Content-Type",
932 | "value": "text/javascript"
933 | },
934 | {
935 | "name": "Content-Encoding",
936 | "value": "gzip"
937 | }
938 | ],
939 | "content": {
940 | "mimeType": "text/javascript",
941 | "size": 11676,
942 | "text": "--- REMOVED ---\n"
943 | },
944 | "redirectURL": "",
945 | "headersSize": 369,
946 | "bodySize": 4453
947 | },
948 | "cache": {},
949 | "timings": {
950 | "blocked": 5000,
951 | "dns": 0,
952 | "connect": 0,
953 | "send": 0,
954 | "wait": 55,
955 | "receive": 2
956 | },
957 | "serverIPAddress": "2001:8d8:1000:30ff:1bb6:8823:a9a3:a003",
958 | "connection": "80"
959 | }
960 | ]
961 | }
962 | }
--------------------------------------------------------------------------------