/* * Licensed to the Ted Dunning under one or more contributor license * agreements. See the NOTICE file that may be * distributed with this work for additional information * regarding copyright ownership. Ted Dunning licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.mapr.synth.samplers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.TextNode; import com.google.common.collect.ImmutableMap; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; import java.io.IOException; import java.io.StringWriter; import java.util.Map; import java.util.Random; /** * Sample a list of headers in the style of those that might accompany a web request */ public class HeaderSampler extends FieldSampler { private Template template; private String prolog; private enum Type { NORMAL, ABABIL, MAL1, MAL2, MAL3 } private Type headerType = Type.NORMAL; private BrowserSampler browser = new BrowserSampler(); private Map<String, StringSampler> headers = ImmutableMap.<String, StringSampler>builder() .put("chrome", new StringSampler("user-agents/chrome")) .put("firefox", new StringSampler("user-agents/firefox")) .put("ie", new StringSampler("user-agents/ie")) .put("mobile", new StringSampler("user-agents/mobile")) .put("opera", new StringSampler("user-agents/opera")) .put("safari", new StringSampler("user-agents/safari")) .build(); private StringSampler language = new LanguageSampler(); private Random gen = new Random(); public void setType(String headerType) throws IOException { this.headerType = Type.valueOf(headerType.toUpperCase()); setupTemplate(); } @SuppressWarnings("unused") public void setProlog(String prolog) { this.prolog = prolog; } // picks which template to use based on header type private void setupTemplate() throws IOException { Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); cfg.setDefaultEncoding("UTF-8"); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); cfg.setTemplateLoader(new ClassTemplateLoader(getClass(), "/web-headers")); String templateName = "header"; switch (headerType) { case MAL3: templateName = "mal3"; break; case ABABIL: templateName = "ababil"; break; default: break; } template = cfg.getTemplate(templateName); } // these methods sample the pieces of the headers String encoding() { switch (headerType) { case MAL1: return "identity"; case MAL2: return " "; default: switch (gen.nextInt(3)) { case 0: return "gzip"; case 1: return "deflate"; case 2: default: return "gzip, deflate"; } } } String userAgent() { if (headerType == Type.ABABIL) { return "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)"; } String br = browser.sample().asText(); StringSampler s = headers.get(br.toLowerCase()); if (s == null) { throw new IllegalStateException("Illegal browser"); } return s.sample().asText(); } String language() { String lang = language.sample().asText(); if (headerType == Type.ABABIL) { return "fr"; } else { return lang + "-" + lang.toUpperCase() + "," + lang + ";q=0.5"; } } String url(boolean isImage) { return String.format("http://foo.bar.com/%06d/%06x%s", gen.nextInt(1_000_000), gen.nextInt(0x1_000_000), isImage ? ".jpg" : ".html"); } String accept(boolean isImage) { if (isImage) { return "image/png,image/*;q=0.8,*/*;q=0.5"; } else { return "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; } } public HeaderSampler() throws IOException { setupTemplate(); } @Override public JsonNode sample() { boolean isImage = gen.nextDouble() < 0.3; Map<String, String> params = ImmutableMap.<String, String>builder() .put("url", url(isImage)) .put("host", String.format("x%03d.foo.com", gen.nextInt(5))) .put("accept", accept(isImage)) .put("userAgent", userAgent()) .put("language", language()) .put("encoding", encoding()) .put("referer", url(false)) .build(); StringWriter out = new StringWriter(); if (prolog != null) { out.append(prolog); } try { template.process(params, out); } catch (TemplateException e) { throw new RuntimeException("Error expanding template", e); } catch (IOException e) { throw new RuntimeException("Error loading template", e); } return new TextNode(out.toString()); } }