Skip to content

Commit

Permalink
Closes #18: adding a special * value for node-address, which causes q…
Browse files Browse the repository at this point in the history
…ueue url to be constructed using the incoming request path
  • Loading branch information
adamw committed Mar 23, 2016
1 parent f4d103d commit 2790b84
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 37 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ log INFO logs and above to the console):

java -Dlogback.configurationFile=my_logback.xml -jar elasticmq-server-0.8.12.jar

How are queue URLs created
--------------------------

Some of the responses include a queue URL. By default the urls will use `http://localhost:9324` as the base URL.
To customize, you should properly set the protocol/host/port/context in the `node-address` setting (see above).

You can also set `node-address.host` to a special value, `*`, which will cause any queue URLs created during a request
to use the path of the incoming request. This might be useful e.g. in containerized (Docker) deployments.

Note that changing the `bind-port` and `bind-hostname` settings does not affect the queue URLs in any way.

Automatically creating queues on startup
----------------------------------------

Expand Down Expand Up @@ -260,11 +271,12 @@ Technology
Change log
----------

#### Version 0.9.0 (pending)
#### Version 0.9.0 (23 Mar 2016)

* replace Spray with Akka
* increase message body size limits
* provide an option to create queues on startup
* add a special node-address setting: `*`, which uses the incoming request url to create queue urls

#### Version 0.8.12 (30 Sep 2015)

Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/org/elasticmq/NodeAddress.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ case class NodeAddress(protocol: String = "http",
host: String = "localhost",
port: Int = 9324,
contextPath: String = "") {
def hostAndPort = host + ":" + port
def fullAddress = protocol + "://" + hostAndPort + contextPath
def hostAndPort: String = host + ":" + port
def fullAddress: String = protocol + "://" + hostAndPort + contextPath
def isWildcard: Boolean = host == "*"
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,17 @@ trait CreateQueueDirectives { this: ElasticMQDirectives with QueueURLModule with
throw new SQSException("AWS.SimpleQueueService.QueueNameExists")
}

respondWith {
<CreateQueueResponse>
<CreateQueueResult>
<QueueUrl>{queueURL(queueData)}</QueueUrl>
</CreateQueueResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</CreateQueueResponse>
queueURL(queueData) { url =>
respondWith {
<CreateQueueResponse>
<CreateQueueResult>
<QueueUrl>{url}</QueueUrl>
</CreateQueueResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</CreateQueueResponse>
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ trait GetQueueUrlDirectives { this: ElasticMQDirectives with QueueURLModule =>
p.action("GetQueueUrl") {
rootPath {
queueDataFromParams(p) { queueData =>
respondWith {
<GetQueueUrlResponse>
<GetQueueUrlResult>
<QueueUrl>{queueURL(queueData)}</QueueUrl>
</GetQueueUrlResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</GetQueueUrlResponse>
queueURL(queueData) { url =>
respondWith {
<GetQueueUrlResponse>
<GetQueueUrlResult>
<QueueUrl>{url}</QueueUrl>
</GetQueueUrlResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</GetQueueUrlResponse>
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ trait ListQueuesDirectives { this: ElasticMQDirectives with QueueURLModule =>
case None => allQueueNames
}

respondWith {
<ListQueuesResponse>
<ListQueuesResult>
{queueNames.map(queueName => <QueueUrl>{queueURL(queueName)}</QueueUrl>)}
</ListQueuesResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</ListQueuesResponse>
baseQueueURL { baseURL =>
respondWith {
<ListQueuesResponse>
<ListQueuesResult>
{queueNames.map(queueName => <QueueUrl>{baseURL + "/" + queueName}</QueueUrl>)}
</ListQueuesResult>
<ResponseMetadata>
<RequestId>{EmptyRequestId}</RequestId>
</ResponseMetadata>
</ListQueuesResponse>
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,32 @@ import akka.stream.ActorMaterializer
import scala.util.control.Exception._
import xml._
import java.security.MessageDigest

import org.elasticmq.util.Logging

import collection.mutable.ArrayBuffer
import akka.actor.{Props, ActorRef, ActorSystem}
import akka.actor.{ActorRef, ActorSystem, Props}
import akka.util.Timeout

import scala.concurrent.{Await, Future}
import org.elasticmq.rest.sqs.directives.ElasticMQDirectives
import org.elasticmq.rest.sqs.Constants._

import scala.xml.EntityRef
import org.elasticmq._
import com.typesafe.config.ConfigFactory
import org.elasticmq.actor.QueueManagerActor
import org.elasticmq.util.NowProvider

import scala.concurrent.duration._
import java.nio.ByteBuffer
import java.io.ByteArrayOutputStream

import scala.collection.immutable.TreeMap
import java.util.concurrent.TimeUnit

import akka.http.scaladsl.server.{Directive1, Directives}

/**
* By default:
* <li>
Expand Down Expand Up @@ -153,7 +161,7 @@ case class TheSQSRestServerBuilder(providedActorSystem: Option[ActorSystem],
val appStartFuture = Http().bindAndHandle(routes, interface, port)

TheSQSRestServerBuilder.this.logger.info("Started SQS rest server, bind address %s:%d, visible server address %s"
.format(interface, port, theServerAddress.fullAddress))
.format(interface, port, if (theServerAddress.isWildcard) "* (depends on incoming request path) "else theServerAddress.fullAddress))

SQSRestServer(appStartFuture, () => {
appStartFuture.flatMap { sb =>
Expand Down Expand Up @@ -298,8 +306,33 @@ trait QueueManagerActorModule {
trait QueueURLModule {
def serverAddress: NodeAddress

def queueURL(queueData: QueueData) = List(serverAddress.fullAddress, QueueUrlContext, queueData.name).mkString("/")
def queueURL(queueName: String) = List(serverAddress.fullAddress, QueueUrlContext, queueName).mkString("/")
import Directives._

def baseQueueURL: Directive1[String] = {
val baseAddress = if (serverAddress.isWildcard) {
extractRequest.map { req =>
val incomingAddress = req.uri.copy(rawQueryString = None, fragment = None).toString

val incomingAddressNoSlash = if (incomingAddress.endsWith("/")) {
incomingAddress.substring(0, incomingAddress.length - 1)
} else incomingAddress

// removing the final /queue or /queue/ if present, it will be re-added later
if (incomingAddressNoSlash.endsWith(QueueUrlContext)) {
incomingAddressNoSlash.substring(0, incomingAddressNoSlash.length - QueueUrlContext.length - 1)
} else incomingAddressNoSlash
}
} else {
provide(serverAddress.fullAddress)
}

baseAddress.map(_ + "/" + QueueUrlContext)
}


def queueURL(queueData: QueueData): Directive1[String] = {
baseQueueURL.map(base => base + "/" + queueData.name)
}
}

object SQSLimits extends Enumeration {
Expand Down
4 changes: 2 additions & 2 deletions server/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ storage {
// What is the outside visible address of this ElasticMQ node
// Used to create the queue URL (may be different from bind address!)
node-address {
protocol = http
host = localhost
protocol = "http"
host = "localhost"
port = 9324
context-path = ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ElasticMQServerConfig(config: Config) {
}
}

// What is the outside visible address of this ElasticMQ node (used by replication and rest-sqs)
// What is the outside visible address of this ElasticMQ node (used by rest-sqs)

val nodeAddress = {
val subConfig = config.getConfig("node-address")
Expand Down

0 comments on commit 2790b84

Please sign in to comment.