|
Lift Framework example source code file (HttpHelpers.scala)
The Lift Framework HttpHelpers.scala source code/* * Copyright 2006-2011 WorldWide Conferencing, LLC * * Licensed 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 net.liftweb package util import java.net.{URLDecoder, URLEncoder} import scala.collection.mutable.ListBuffer import scala.xml._ import scala.collection.{Map} import scala.collection.mutable.HashMap import java.util.concurrent.atomic.AtomicLong import common._ object HttpHelpers extends ListHelpers with StringHelpers trait HttpHelpers { self: ListHelpers with StringHelpers => /** * The list of known suffixes used to split the URI into path parts and suffixes. */ val knownSuffixes: Set[String] = Set("json","rss","atom","do","3dm", "3dmf","a","aab","aam","aas","abc","acgi","afl","ai","aif","aifc","aiff", "aim","aip","ani","aos","aps","arc","arj","art","asf","asm","asp","asx","au","avi","avs", "bcpio","bin","bm","bmp","boo","book","boz","bsh","bz","bz2","c","c++","cat","cc","ccad", "cco","cdf","cer","cha","chat","class","com","conf","cpio","cpp","cpt","crl","crt","csh", "css","cxx","dcr","deepv","def","der","dif","dir","dl","doc","dot","dp","drw","dump","dv", "dvi","dwf","dwg","dxf","dxr","el","elc","env","eps","es","etx","evy","exe","f","f77", "f90","fdf","fif","fli","flo","flx","fmf","for","fpx","frl","funk","g","g3","gif","gl","gsd", "gsm","gsp","gss","gtar","gz","gzip","h","hdf","help","hgl","hh","hlb","hlp","hpg","hpgl", "hqx","hta","htc","htm","html","htmls","htt","htx","ice","ico","idc","ief","iefs","iges","igs", "ima","imap","inf","ins","ip","isu","it","iv","ivr","ivy","jam","jav","java","jcm","jfif", "jfif-tbnl","jpe","jpeg","jpg","jps","js","jut","kar","ksh","la","lam","latex","lha","lhx", "list","lma","log","lsp","lst","lsx","ltx","lzh","lzx","m","m1v","m2a","m2v","m3u","man","map", "mar","mbd","mc$","mcd","mcf","mcp","me","mht","mhtml","mid","midi","mif","mime","mjf","mjpg", "mm","mme","mod","moov","mov","movie","mp2","mp3","mpa","mpc","mpe","mpeg","mpg","mpga","mpp", "mpt","mpv","mpx","mrc","ms","mv","my","mzz","nap","naplps","nc","ncm","nif","niff","nix", "nsc","nvd","o","oda","omc","omcd","omcr","p","p10","p12","p7a","p7c","p7m","p7r","p7s","part", "pas","pbm","pcl","pct","pcx","pdb","pdf","pfunk","pgm","pic","pict","pkg","pko","pl","plx","pm", "pm4","pm5","png","pnm","pot","pov","ppa","ppm","pps","ppt","ppz","pre","prt","ps","psd", "pvu","pwz","py","pyc","qcp","qd3","qd3d","qif","qt","qtc","qti","qtif","ra","ram","ras", "rast","rexx","rf","rgb","rm","rmi","rmm","rmp","rng","rnx","roff","rp","rpm","rt","rtf","rtx", "rv","s","s3m","saveme","sbk","scm","sdml","sdp","sdr","sea","set","sgm","sgml","sh","shar", "shtml","sid","sit","skd","skm","skp","skt","sl","smi","smil","snd","sol","spc","spl","spr", "sprite","src","ssi","ssm","sst","step","stl","stp","sv4cpio","sv4crc","svf","svr","swf","t", "talk","tar","tbk","tcl","tcsh","tex","texi","texinfo","text","tgz","tif","tiff","tr","tsi", "tsp","tsv","turbot","txt","uil","uni","unis","unv","uri","uris","ustar","uu","uue","vcd","vcs", "vda","vdo","vew","viv","vivo","vmd","vmf","voc","vos","vox","vqe","vqf","vql","vrml","vrt", "vsd","vst","vsw","w60","w61","w6w","wav","wb1","wbmp","web","wiz","wk1","wmf","wml","wmlc", "wmls","wmlsc","word","wp","wp5","wp6","wpd","wq1","wri","wrl","wrz","wsc","wsrc","wtk","x-png", "xbm","xdr","xgz","xif","xl","xla","xlb","xlc","xld","xlk","xll","xlm","xls","xlt","xlv","xlw", "xm","xml","xmz","xpix","xpm","xsr","xwd","xyz","z","zip","zoo","zsh") /** * URL decode the string. * * This is a pass-through to Java's URL decode with UTF-8 */ def urlDecode(in : String) = URLDecoder.decode(in, "UTF-8") /** * URL encode the string. * * This is a pass-through to Java's URL encode with UTF-8 */ def urlEncode(in : String) = URLEncoder.encode(in, "UTF-8") /** * Take a list of name/value parse and turn them into a URL query string * * @param params the name/value pairs * @return a valid query string */ def paramsToUrlParams(params: List[(String, String)]): String = params.map { case (n, v) => urlEncode(n) + "=" + urlEncode(v) }.mkString("&") /** * Append parameters to a URL * * @param url the url to append the params to * @param params the parameters (name/value) to append to the URL * * @return the url with the parameters appended */ def appendParams(url: String, params: Seq[(String, String)]): String = params.toList match { case Nil => url case xs if !url.contains("?") => url + "?" + paramsToUrlParams(xs) case xs => url + "&" + paramsToUrlParams(xs) } /** * Given a map of HTTP properties, return true if the "Content-type" * value in the map is either "text/html" or "application/xhtml+xml" * @param in Map which may contain a key named Content-Type * @return true if there is a pair ("Content-Type", "text/html") or * ("Content-Type", "application/xhtml+xml") */ def couldBeHtml(in: Map[String, String]): Boolean = in match { case null => true case n => { n.get("Content-Type") match { case Some(s) => { (s.toLowerCase == "text/html") || (s.toLowerCase == "application/xhtml+xml") } case None => true } } } /** * Return true if the xml doesn't contain an <html> tag */ def noHtmlTag(in: NodeSeq): Boolean = findElems(in)(_.label == "html").length != 1 /** * Transform a general Map to a nutable HashMap */ def toHashMap[A,B](in : Map[A,B]) : HashMap[A,B] = { val ret = new HashMap[A,B]; in.keysIterator.foreach { k => ret += Pair(k, in(k)) } ret } /** * Ensure that all the appropriate fields are in the header. */ def insureField(toInsure: List[(String, String)], headers: List[(String, String)]): List[(String, String)] = { def insureField_inner(toInsure : List[(String, String)], field : (String, String)): List[(String, String)] = toInsure.ciGet(field._1) match { case Full(_) => toInsure case _ => field :: toInsure } headers match { case Nil => toInsure case x :: xs => insureField(insureField_inner(toInsure, x), xs) } } /** * Transform a pair (name: String, value: Any) to an unprefixed XML attribute name="value" */ implicit def pairToUnprefixed(in: (String, Any)): MetaData = { val value: Option[NodeSeq] = in._2 match { case null => None case js: ToJsCmd => Some(Text(js.toJsCmd)) case n: Node => Some(n) case n: NodeSeq => Some(n) case None => None case Some(n: Node) => Some(n) case Some(n: NodeSeq) => Some(n) case Empty => None case Full(n: Node) => Some(n) case Full(n: NodeSeq) => Some(n) case s => Some(Text(s.toString)) } value.map(v => new UnprefixedAttribute(in._1, v, Null)) getOrElse Null } /** * If the specified Elem has an attribute named 'id', return it, otherwise * construct a new Elem with a randomly generated id attribute and return the pair * * @param in the element to test & add 'id' to * @return the new element and the id */ def findOrAddId(in: Elem): (Elem, String) = (in \ "@id").toList match { case Nil => { val id = nextFuncName (in % ("id" -> id), id) } case x :: xs => (in, x.text) } /** * Within a NodeSeq, find the first elem and run it through * the function. Return the resulting NodeSeq */ def evalElemWithId(f: (String, Elem) => NodeSeq)(ns: NodeSeq): NodeSeq = { var found = false ns.flatMap { case e: Elem if !found => { found = true val (ne, id) = findOrAddId(e) f(id, ne) } case x => x } } /** * Given a URL and a Lift function String, append the function * even if the URL has query params and a # */ def appendFuncToURL(url: String, funcStr: String): String = splitAtHash(url){to => to + (if (to.indexOf("?") >= 0) "&" else "?") + funcStr} /** * Split a String at the Hash sign, run the function * on the non-# side and then append the hash side */ def splitAtHash(str: String)(f: String => String): String = str.indexOf("#") match { case idx if idx < 0 => f(str) case idx => f(str.substring(0, idx)) + str.substring(idx) } /** * Given a list of query parameters, append them to the * URL taking into account # and if there are any other query * parameters */ def appendQueryParameters(url: String, params: List[(String, String)]): String = params match { case Nil => url case ps => splitAtHash(url) { to => to + (if (to.indexOf("?") >= 0) "&" else "?") + ps.map{case (n, v) => urlEncode(n) + "=" + urlEncode(v)}. mkString("&") } } private val serial = new AtomicLong(math.abs(Helpers.randomLong(Helpers.millis)) + 1000000L) /** * Get a monotonically increasing number that's guaranteed to be unique for the * current session */ def nextNum = serial.incrementAndGet /** * Find the elements of the specified NodeSeq that match * the specified predicate and concatenate them into * a resulting NodeSeq. * * @param nodes - the NodeSeq to search for elements matching the predicate * @param f - the predicate to match elements with * @return the NodeSeq resulting from concatenation of the matched elements. */ def findElems(nodes: NodeSeq)(f: Elem => Boolean): NodeSeq = { val ret = new ListBuffer[Elem] def find(what: NodeSeq) { what.foreach { case Group(g) => find(g) case e: Elem => if (f(e)) ret += e find(e.child) case n => find(n.child) } } find(nodes) ret.toList } /** * Map the specified function over the elements of the * specified NodeSeq and return the concatenated result. * This is essentially a container-type-transforming flatMap operation. */ def findInElems[T](nodes: NodeSeq)(f: Elem => Iterable[T]): List[T] = { val ret = new ListBuffer[T] def find(what: NodeSeq) { what.foreach { case Group(g) => find(g) case e: Elem => ret ++= f(e) find(e.child) case n => find(n.child) } } find(nodes) ret.toList } /** * Get a guaranteed unique field name * (16 or 17 letters and numbers, starting with a letter) */ def nextFuncName: String = nextFuncName(0) /** * Get a guaranteed unique field name * (16 or 17 letters and numbers, starting with a letter) */ def nextFuncName(seed: Long): String = { val sb = new StringBuilder(24) sb.append('F') sb.append(nextNum + seed) // sb.append('_') sb.append(randomString(6)) sb.toString } def findKids(in: NodeSeq, prefix: String, label: String): NodeSeq = in.filter(n => n.label == label && n.prefix == prefix).flatMap(_.child) def deepFindKids(in: NodeSeq, prefix: String, label: String): NodeSeq = { val ret: ListBuffer[Node] = new ListBuffer def doIt(in: NodeSeq) { in.foreach { case e: Elem if e.prefix == prefix && e.label == label => e.child.foreach(ret.+=) case g: Group => doIt(g.nodes) case n => doIt(n.child) } } doIt(in) ret.toList } } /** * TODO: Is this something that can be converted to a JavaScript Command */ trait ToJsCmd { def toJsCmd: String } object CheckNodeSeq { def unapply(in: Any): Option[NodeSeq] = in match { case Some(ns: NodeSeq) => Some(ns) case Full(ns: NodeSeq) => Some(ns) case Some(sq: Seq[_]) if sq.forall(_.isInstanceOf[Node])=> val ns: NodeSeq = sq.asInstanceOf[Seq[Node]] Some(ns) case Full(sq: Seq[_]) if sq.forall(_.isInstanceOf[Node])=> val ns: NodeSeq = sq.asInstanceOf[Seq[Node]] Some(ns) case ns: NodeSeq => Some(ns) case sq: Seq[_] if sq.forall(_.isInstanceOf[Node])=> val ns: NodeSeq = sq.asInstanceOf[Seq[Node]] Some(ns) case _ => None } } Other Lift Framework examples (source code examples)Here is a short list of links related to this Lift Framework HttpHelpers.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.